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 if GlobalData
.gBinCacheDest
:
690 content
+= 'Cache of .efi location: '
691 content
+= str(GlobalData
.gBinCacheDest
)
692 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'BuildOptions'), content
, False)
695 # Create PcdToken Number file for Dynamic/DynamicEx Pcd.
697 PcdTokenNumber
= 'PcdTokenNumber: '
698 if Pa
.PcdTokenNumber
:
699 if Pa
.DynamicPcdList
:
700 for Pcd
in Pa
.DynamicPcdList
:
701 PcdTokenNumber
+= os
.linesep
702 PcdTokenNumber
+= str((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
))
703 PcdTokenNumber
+= ' : '
704 PcdTokenNumber
+= str(Pa
.PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
])
705 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'PcdTokenNumber'), PcdTokenNumber
, False)
708 # Get set of workspace metafiles
710 AllWorkSpaceMetaFiles
= self
._GetMetaFiles
(Target
, Toolchain
, Arch
)
713 # Retrieve latest modified time of all metafiles
716 for f
in AllWorkSpaceMetaFiles
:
717 if os
.stat(f
)[8] > SrcTimeStamp
:
718 SrcTimeStamp
= os
.stat(f
)[8]
719 self
._SrcTimeStamp
= SrcTimeStamp
721 if GlobalData
.gUseHashCache
:
723 for files
in AllWorkSpaceMetaFiles
:
724 if files
.endswith('.dec'):
730 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'AutoGen.hash'), m
.hexdigest(), True)
731 GlobalData
.gPlatformHash
= m
.hexdigest()
734 # Write metafile list to build directory
736 AutoGenFilePath
= os
.path
.join(self
.BuildDir
, 'AutoGen')
737 if os
.path
.exists (AutoGenFilePath
):
738 os
.remove(AutoGenFilePath
)
739 if not os
.path
.exists(self
.BuildDir
):
740 os
.makedirs(self
.BuildDir
)
741 with
open(os
.path
.join(self
.BuildDir
, 'AutoGen'), 'w+') as file:
742 for f
in AllWorkSpaceMetaFiles
:
746 def _GenPkgLevelHash(self
, Pkg
):
747 PkgDir
= os
.path
.join(self
.BuildDir
, Pkg
.Arch
, Pkg
.PackageName
)
748 CreateDirectory(PkgDir
)
749 HashFile
= os
.path
.join(PkgDir
, Pkg
.PackageName
+ '.hash')
751 # Get .dec file's hash value
752 f
= open(Pkg
.MetaFile
.Path
, 'r')
756 # Get include files hash value
758 for inc
in Pkg
.Includes
:
759 for Root
, Dirs
, Files
in os
.walk(str(inc
)):
761 File_Path
= os
.path
.join(Root
, File
)
762 f
= open(File_Path
, 'r')
766 SaveFileOnChange(HashFile
, m
.hexdigest(), True)
767 if Pkg
.PackageName
not in GlobalData
.gPackageHash
[Pkg
.Arch
]:
768 GlobalData
.gPackageHash
[Pkg
.Arch
][Pkg
.PackageName
] = m
.hexdigest()
770 def _GetMetaFiles(self
, Target
, Toolchain
, Arch
):
771 AllWorkSpaceMetaFiles
= set()
776 AllWorkSpaceMetaFiles
.add (self
.FdfFile
.Path
)
778 FdfFiles
= GlobalData
.gFdfParser
.GetAllIncludedFile()
780 AllWorkSpaceMetaFiles
.add (f
.FileName
)
784 AllWorkSpaceMetaFiles
.add(self
.MetaFile
.Path
)
787 # add build_rule.txt & tools_def.txt
789 AllWorkSpaceMetaFiles
.add(os
.path
.join(GlobalData
.gConfDirectory
, gDefaultBuildRuleFile
))
790 AllWorkSpaceMetaFiles
.add(os
.path
.join(GlobalData
.gConfDirectory
, gDefaultToolsDefFile
))
792 # add BuildOption metafile
794 AllWorkSpaceMetaFiles
.add(os
.path
.join(self
.BuildDir
, 'BuildOptions'))
796 # add PcdToken Number file for Dynamic/DynamicEx Pcd
798 AllWorkSpaceMetaFiles
.add(os
.path
.join(self
.BuildDir
, 'PcdTokenNumber'))
800 for Arch
in self
.ArchList
:
801 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
802 PGen
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
807 for Package
in PGen
.PackageList
:
808 AllWorkSpaceMetaFiles
.add(Package
.MetaFile
.Path
)
813 for filePath
in Platform
._RawData
.IncludedFiles
:
814 AllWorkSpaceMetaFiles
.add(filePath
.Path
)
816 return AllWorkSpaceMetaFiles
818 ## _CheckDuplicateInFV() method
820 # Check whether there is duplicate modules/files exist in FV section.
821 # The check base on the file GUID;
823 def _CheckDuplicateInFV(self
, Fdf
):
824 for Fv
in Fdf
.Profile
.FvDict
:
826 for FfsFile
in Fdf
.Profile
.FvDict
[Fv
].FfsList
:
827 if FfsFile
.InfFileName
and FfsFile
.NameGuid
== None:
832 for Pa
in self
.AutoGenObjectList
:
835 for Module
in Pa
.ModuleAutoGenList
:
836 if path
.normpath(Module
.MetaFile
.File
) == path
.normpath(FfsFile
.InfFileName
):
838 if not Module
.Guid
.upper() in _GuidDict
.keys():
839 _GuidDict
[Module
.Guid
.upper()] = FfsFile
842 EdkLogger
.error("build",
844 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile
.CurrentLineNum
,
845 FfsFile
.CurrentLineContent
,
846 _GuidDict
[Module
.Guid
.upper()].CurrentLineNum
,
847 _GuidDict
[Module
.Guid
.upper()].CurrentLineContent
,
848 Module
.Guid
.upper()),
849 ExtraData
=self
.FdfFile
)
851 # Some INF files not have entity in DSC file.
854 if FfsFile
.InfFileName
.find('$') == -1:
855 InfPath
= NormPath(FfsFile
.InfFileName
)
856 if not os
.path
.exists(InfPath
):
857 EdkLogger
.error('build', GENFDS_ERROR
, "Non-existant Module %s !" % (FfsFile
.InfFileName
))
859 PathClassObj
= PathClass(FfsFile
.InfFileName
, self
.WorkspaceDir
)
861 # Here we just need to get FILE_GUID from INF file, use 'COMMON' as ARCH attribute. and use
862 # BuildObject from one of AutoGenObjectList is enough.
864 InfObj
= self
.AutoGenObjectList
[0].BuildDatabase
.WorkspaceDb
.BuildObject
[PathClassObj
, 'COMMON', self
.BuildTarget
, self
.ToolChain
]
865 if not InfObj
.Guid
.upper() in _GuidDict
.keys():
866 _GuidDict
[InfObj
.Guid
.upper()] = FfsFile
868 EdkLogger
.error("build",
870 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile
.CurrentLineNum
,
871 FfsFile
.CurrentLineContent
,
872 _GuidDict
[InfObj
.Guid
.upper()].CurrentLineNum
,
873 _GuidDict
[InfObj
.Guid
.upper()].CurrentLineContent
,
874 InfObj
.Guid
.upper()),
875 ExtraData
=self
.FdfFile
)
878 if FfsFile
.NameGuid
!= None:
879 _CheckPCDAsGuidPattern
= re
.compile("^PCD\(.+\..+\)$")
882 # If the NameGuid reference a PCD name.
883 # The style must match: PCD(xxxx.yyy)
885 if _CheckPCDAsGuidPattern
.match(FfsFile
.NameGuid
):
887 # Replace the PCD value.
889 _PcdName
= FfsFile
.NameGuid
.lstrip("PCD(").rstrip(")")
891 for Pa
in self
.AutoGenObjectList
:
893 for PcdItem
in Pa
.AllPcdList
:
894 if (PcdItem
.TokenSpaceGuidCName
+ "." + PcdItem
.TokenCName
) == _PcdName
:
896 # First convert from CFormatGuid to GUID string
898 _PcdGuidString
= GuidStructureStringToGuidString(PcdItem
.DefaultValue
)
900 if not _PcdGuidString
:
902 # Then try Byte array.
904 _PcdGuidString
= GuidStructureByteArrayToGuidString(PcdItem
.DefaultValue
)
906 if not _PcdGuidString
:
908 # Not Byte array or CFormat GUID, raise error.
910 EdkLogger
.error("build",
912 "The format of PCD value is incorrect. PCD: %s , Value: %s\n" % (_PcdName
, PcdItem
.DefaultValue
),
913 ExtraData
=self
.FdfFile
)
915 if not _PcdGuidString
.upper() in _GuidDict
.keys():
916 _GuidDict
[_PcdGuidString
.upper()] = FfsFile
920 EdkLogger
.error("build",
922 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile
.CurrentLineNum
,
923 FfsFile
.CurrentLineContent
,
924 _GuidDict
[_PcdGuidString
.upper()].CurrentLineNum
,
925 _GuidDict
[_PcdGuidString
.upper()].CurrentLineContent
,
926 FfsFile
.NameGuid
.upper()),
927 ExtraData
=self
.FdfFile
)
929 if not FfsFile
.NameGuid
.upper() in _GuidDict
.keys():
930 _GuidDict
[FfsFile
.NameGuid
.upper()] = FfsFile
933 # Two raw file GUID conflict.
935 EdkLogger
.error("build",
937 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile
.CurrentLineNum
,
938 FfsFile
.CurrentLineContent
,
939 _GuidDict
[FfsFile
.NameGuid
.upper()].CurrentLineNum
,
940 _GuidDict
[FfsFile
.NameGuid
.upper()].CurrentLineContent
,
941 FfsFile
.NameGuid
.upper()),
942 ExtraData
=self
.FdfFile
)
945 def _CheckPcdDefineAndType(self
):
947 "FixedAtBuild", "PatchableInModule", "FeatureFlag",
948 "Dynamic", #"DynamicHii", "DynamicVpd",
949 "DynamicEx", # "DynamicExHii", "DynamicExVpd"
952 # This dict store PCDs which are not used by any modules with specified arches
954 for Pa
in self
.AutoGenObjectList
:
955 # Key of DSC's Pcds dictionary is PcdCName, TokenSpaceGuid
956 for Pcd
in Pa
.Platform
.Pcds
:
957 PcdType
= Pa
.Platform
.Pcds
[Pcd
].Type
959 # If no PCD type, this PCD comes from FDF
963 # Try to remove Hii and Vpd suffix
964 if PcdType
.startswith("DynamicEx"):
965 PcdType
= "DynamicEx"
966 elif PcdType
.startswith("Dynamic"):
969 for Package
in Pa
.PackageList
:
970 # Key of DEC's Pcds dictionary is PcdCName, TokenSpaceGuid, PcdType
971 if (Pcd
[0], Pcd
[1], PcdType
) in Package
.Pcds
:
973 for Type
in PcdTypeList
:
974 if (Pcd
[0], Pcd
[1], Type
) in Package
.Pcds
:
978 "Type [%s] of PCD [%s.%s] in DSC file doesn't match the type [%s] defined in DEC file." \
979 % (Pa
.Platform
.Pcds
[Pcd
].Type
, Pcd
[1], Pcd
[0], Type
),
984 UnusedPcd
.setdefault(Pcd
, []).append(Pa
.Arch
)
986 for Pcd
in UnusedPcd
:
989 "The PCD was not specified by any INF module in the platform for the given architecture.\n"
990 "\tPCD: [%s.%s]\n\tPlatform: [%s]\n\tArch: %s"
991 % (Pcd
[1], Pcd
[0], os
.path
.basename(str(self
.MetaFile
)), str(UnusedPcd
[Pcd
])),
996 return "%s [%s]" % (self
.MetaFile
, ", ".join(self
.ArchList
))
998 ## Return the directory to store FV files
1000 if self
._FvDir
== None:
1001 self
._FvDir
= path
.join(self
.BuildDir
, 'FV')
1004 ## Return the directory to store all intermediate and final files built
1005 def _GetBuildDir(self
):
1006 if self
._BuildDir
== None:
1007 return self
.AutoGenObjectList
[0].BuildDir
1009 ## Return the build output directory platform specifies
1010 def _GetOutputDir(self
):
1011 return self
.Platform
.OutputDirectory
1013 ## Return platform name
1015 return self
.Platform
.PlatformName
1017 ## Return meta-file GUID
1019 return self
.Platform
.Guid
1021 ## Return platform version
1022 def _GetVersion(self
):
1023 return self
.Platform
.Version
1025 ## Return paths of tools
1026 def _GetToolDefinition(self
):
1027 return self
.AutoGenObjectList
[0].ToolDefinition
1029 ## Return directory of platform makefile
1031 # @retval string Makefile directory
1033 def _GetMakeFileDir(self
):
1034 if self
._MakeFileDir
== None:
1035 self
._MakeFileDir
= self
.BuildDir
1036 return self
._MakeFileDir
1038 ## Return build command string
1040 # @retval string Build command string
1042 def _GetBuildCommand(self
):
1043 if self
._BuildCommand
== None:
1044 # BuildCommand should be all the same. So just get one from platform AutoGen
1045 self
._BuildCommand
= self
.AutoGenObjectList
[0].BuildCommand
1046 return self
._BuildCommand
1048 ## Check the PCDs token value conflict in each DEC file.
1050 # Will cause build break and raise error message while two PCDs conflict.
1054 def _CheckAllPcdsTokenValueConflict(self
):
1055 for Pa
in self
.AutoGenObjectList
:
1056 for Package
in Pa
.PackageList
:
1057 PcdList
= Package
.Pcds
.values()
1058 PcdList
.sort(lambda x
, y
: cmp(int(x
.TokenValue
, 0), int(y
.TokenValue
, 0)))
1060 while (Count
< len(PcdList
) - 1) :
1061 Item
= PcdList
[Count
]
1062 ItemNext
= PcdList
[Count
+ 1]
1064 # Make sure in the same token space the TokenValue should be unique
1066 if (int(Item
.TokenValue
, 0) == int(ItemNext
.TokenValue
, 0)):
1067 SameTokenValuePcdList
= []
1068 SameTokenValuePcdList
.append(Item
)
1069 SameTokenValuePcdList
.append(ItemNext
)
1070 RemainPcdListLength
= len(PcdList
) - Count
- 2
1071 for ValueSameCount
in range(RemainPcdListLength
):
1072 if int(PcdList
[len(PcdList
) - RemainPcdListLength
+ ValueSameCount
].TokenValue
, 0) == int(Item
.TokenValue
, 0):
1073 SameTokenValuePcdList
.append(PcdList
[len(PcdList
) - RemainPcdListLength
+ ValueSameCount
])
1077 # Sort same token value PCD list with TokenGuid and TokenCName
1079 SameTokenValuePcdList
.sort(lambda x
, y
: cmp("%s.%s" % (x
.TokenSpaceGuidCName
, x
.TokenCName
), "%s.%s" % (y
.TokenSpaceGuidCName
, y
.TokenCName
)))
1080 SameTokenValuePcdListCount
= 0
1081 while (SameTokenValuePcdListCount
< len(SameTokenValuePcdList
) - 1):
1083 TemListItem
= SameTokenValuePcdList
[SameTokenValuePcdListCount
]
1084 TemListItemNext
= SameTokenValuePcdList
[SameTokenValuePcdListCount
+ 1]
1086 if (TemListItem
.TokenSpaceGuidCName
== TemListItemNext
.TokenSpaceGuidCName
) and (TemListItem
.TokenCName
!= TemListItemNext
.TokenCName
):
1087 for PcdItem
in GlobalData
.MixedPcd
:
1088 if (TemListItem
.TokenCName
, TemListItem
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
] or \
1089 (TemListItemNext
.TokenCName
, TemListItemNext
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
1095 "The TokenValue [%s] of PCD [%s.%s] is conflict with: [%s.%s] in %s"\
1096 % (TemListItem
.TokenValue
, TemListItem
.TokenSpaceGuidCName
, TemListItem
.TokenCName
, TemListItemNext
.TokenSpaceGuidCName
, TemListItemNext
.TokenCName
, Package
),
1099 SameTokenValuePcdListCount
+= 1
1100 Count
+= SameTokenValuePcdListCount
1103 PcdList
= Package
.Pcds
.values()
1104 PcdList
.sort(lambda x
, y
: cmp("%s.%s" % (x
.TokenSpaceGuidCName
, x
.TokenCName
), "%s.%s" % (y
.TokenSpaceGuidCName
, y
.TokenCName
)))
1106 while (Count
< len(PcdList
) - 1) :
1107 Item
= PcdList
[Count
]
1108 ItemNext
= PcdList
[Count
+ 1]
1110 # Check PCDs with same TokenSpaceGuidCName.TokenCName have same token value as well.
1112 if (Item
.TokenSpaceGuidCName
== ItemNext
.TokenSpaceGuidCName
) and (Item
.TokenCName
== ItemNext
.TokenCName
) and (int(Item
.TokenValue
, 0) != int(ItemNext
.TokenValue
, 0)):
1116 "The TokenValue [%s] of PCD [%s.%s] in %s defined in two places should be same as well."\
1117 % (Item
.TokenValue
, Item
.TokenSpaceGuidCName
, Item
.TokenCName
, Package
),
1121 ## Generate fds command
1122 def _GenFdsCommand(self
):
1123 return (GenMake
.TopLevelMakefile(self
)._TEMPLATE
_.Replace(GenMake
.TopLevelMakefile(self
)._TemplateDict
)).strip()
1125 ## Create makefile for the platform and modules in it
1127 # @param CreateDepsMakeFile Flag indicating if the makefile for
1128 # modules will be created as well
1130 def CreateMakeFile(self
, CreateDepsMakeFile
=False):
1131 if CreateDepsMakeFile
:
1132 for Pa
in self
.AutoGenObjectList
:
1133 Pa
.CreateMakeFile(CreateDepsMakeFile
)
1135 ## Create autogen code for platform and modules
1137 # Since there's no autogen code for platform, this method will do nothing
1138 # if CreateModuleCodeFile is set to False.
1140 # @param CreateDepsCodeFile Flag indicating if creating module's
1141 # autogen code file or not
1143 def CreateCodeFile(self
, CreateDepsCodeFile
=False):
1144 if not CreateDepsCodeFile
:
1146 for Pa
in self
.AutoGenObjectList
:
1147 Pa
.CreateCodeFile(CreateDepsCodeFile
)
1149 ## Create AsBuilt INF file the platform
1151 def CreateAsBuiltInf(self
):
1154 Name
= property(_GetName
)
1155 Guid
= property(_GetGuid
)
1156 Version
= property(_GetVersion
)
1157 OutputDir
= property(_GetOutputDir
)
1159 ToolDefinition
= property(_GetToolDefinition
) # toolcode : tool path
1161 BuildDir
= property(_GetBuildDir
)
1162 FvDir
= property(_GetFvDir
)
1163 MakeFileDir
= property(_GetMakeFileDir
)
1164 BuildCommand
= property(_GetBuildCommand
)
1165 GenFdsCommand
= property(_GenFdsCommand
)
1167 ## AutoGen class for platform
1169 # PlatformAutoGen class will process the original information in platform
1170 # file in order to generate makefile for platform.
1172 class PlatformAutoGen(AutoGen
):
1174 # Used to store all PCDs for both PEI and DXE phase, in order to generate
1175 # correct PCD database
1178 _NonDynaPcdList_
= []
1182 # The priority list while override build option
1184 PrioList
= {"0x11111" : 16, # TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE (Highest)
1185 "0x01111" : 15, # ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
1186 "0x10111" : 14, # TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE
1187 "0x00111" : 13, # ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE
1188 "0x11011" : 12, # TARGET_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
1189 "0x01011" : 11, # ******_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
1190 "0x10011" : 10, # TARGET_*********_****_COMMANDTYPE_ATTRIBUTE
1191 "0x00011" : 9, # ******_*********_****_COMMANDTYPE_ATTRIBUTE
1192 "0x11101" : 8, # TARGET_TOOLCHAIN_ARCH_***********_ATTRIBUTE
1193 "0x01101" : 7, # ******_TOOLCHAIN_ARCH_***********_ATTRIBUTE
1194 "0x10101" : 6, # TARGET_*********_ARCH_***********_ATTRIBUTE
1195 "0x00101" : 5, # ******_*********_ARCH_***********_ATTRIBUTE
1196 "0x11001" : 4, # TARGET_TOOLCHAIN_****_***********_ATTRIBUTE
1197 "0x01001" : 3, # ******_TOOLCHAIN_****_***********_ATTRIBUTE
1198 "0x10001" : 2, # TARGET_*********_****_***********_ATTRIBUTE
1199 "0x00001" : 1} # ******_*********_****_***********_ATTRIBUTE (Lowest)
1201 ## The real constructor of PlatformAutoGen
1203 # This method is not supposed to be called by users of PlatformAutoGen. It's
1204 # only used by factory method __new__() to do real initialization work for an
1205 # object of PlatformAutoGen
1207 # @param Workspace WorkspaceAutoGen object
1208 # @param PlatformFile Platform file (DSC file)
1209 # @param Target Build target (DEBUG, RELEASE)
1210 # @param Toolchain Name of tool chain
1211 # @param Arch arch of the platform supports
1213 def _Init(self
, Workspace
, PlatformFile
, Target
, Toolchain
, Arch
):
1214 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen platform [%s] [%s]" % (PlatformFile
, Arch
))
1215 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (PlatformFile
, Arch
, Toolchain
, Target
)
1217 self
.MetaFile
= PlatformFile
1218 self
.Workspace
= Workspace
1219 self
.WorkspaceDir
= Workspace
.WorkspaceDir
1220 self
.ToolChain
= Toolchain
1221 self
.BuildTarget
= Target
1223 self
.SourceDir
= PlatformFile
.SubDir
1224 self
.SourceOverrideDir
= None
1225 self
.FdTargetList
= self
.Workspace
.FdTargetList
1226 self
.FvTargetList
= self
.Workspace
.FvTargetList
1227 self
.AllPcdList
= []
1228 # get the original module/package/platform objects
1229 self
.BuildDatabase
= Workspace
.BuildDatabase
1231 # flag indicating if the makefile/C-code file has been created or not
1232 self
.IsMakeFileCreated
= False
1233 self
.IsCodeFileCreated
= False
1235 self
._Platform
= None
1238 self
._Version
= None
1240 self
._BuildRule
= None
1241 self
._SourceDir
= None
1242 self
._BuildDir
= None
1243 self
._OutputDir
= None
1245 self
._MakeFileDir
= None
1246 self
._FdfFile
= None
1248 self
._PcdTokenNumber
= None # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
1249 self
._DynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1250 self
._NonDynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1251 self
._NonDynamicPcdDict
= {}
1253 self
._ToolDefinitions
= None
1254 self
._ToolDefFile
= None # toolcode : tool path
1255 self
._ToolChainFamily
= None
1256 self
._BuildRuleFamily
= None
1257 self
._BuildOption
= None # toolcode : option
1258 self
._EdkBuildOption
= None # edktoolcode : option
1259 self
._EdkIIBuildOption
= None # edkiitoolcode : option
1260 self
._PackageList
= None
1261 self
._ModuleAutoGenList
= None
1262 self
._LibraryAutoGenList
= None
1263 self
._BuildCommand
= None
1264 self
._AsBuildInfList
= []
1265 self
._AsBuildModuleList
= []
1266 if GlobalData
.gFdfParser
!= None:
1267 self
._AsBuildInfList
= GlobalData
.gFdfParser
.Profile
.InfList
1268 for Inf
in self
._AsBuildInfList
:
1269 InfClass
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, self
.Arch
)
1270 M
= self
.BuildDatabase
[InfClass
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1271 if not M
.IsSupportedArch
:
1273 self
._AsBuildModuleList
.append(InfClass
)
1274 # get library/modules for build
1275 self
.LibraryBuildDirectoryList
= []
1276 self
.ModuleBuildDirectoryList
= []
1280 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
1282 ## Create autogen code for platform and modules
1284 # Since there's no autogen code for platform, this method will do nothing
1285 # if CreateModuleCodeFile is set to False.
1287 # @param CreateModuleCodeFile Flag indicating if creating module's
1288 # autogen code file or not
1290 def CreateCodeFile(self
, CreateModuleCodeFile
=False):
1291 # only module has code to be greated, so do nothing if CreateModuleCodeFile is False
1292 if self
.IsCodeFileCreated
or not CreateModuleCodeFile
:
1295 for Ma
in self
.ModuleAutoGenList
:
1296 Ma
.CreateCodeFile(True)
1298 # don't do this twice
1299 self
.IsCodeFileCreated
= True
1301 ## Generate Fds Command
1302 def _GenFdsCommand(self
):
1303 return self
.Workspace
.GenFdsCommand
1305 ## Create makefile for the platform and mdoules in it
1307 # @param CreateModuleMakeFile Flag indicating if the makefile for
1308 # modules will be created as well
1310 def CreateMakeFile(self
, CreateModuleMakeFile
=False):
1311 if CreateModuleMakeFile
:
1312 for ModuleFile
in self
.Platform
.Modules
:
1313 Ma
= ModuleAutoGen(self
.Workspace
, ModuleFile
, self
.BuildTarget
,
1314 self
.ToolChain
, self
.Arch
, self
.MetaFile
)
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 if (self
.Workspace
.ArchList
[-1] == self
.Arch
):
1561 for Pcd
in self
._DynamicPcdList
:
1562 # just pick the a value to determine whether is unicode string type
1563 Sku
= Pcd
.SkuInfoList
[Pcd
.SkuInfoList
.keys()[0]]
1564 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1566 PcdValue
= Sku
.DefaultValue
1567 if Pcd
.DatumType
== 'VOID*' and PcdValue
.startswith("L"):
1568 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
1569 UnicodePcdArray
.append(Pcd
)
1570 elif len(Sku
.VariableName
) > 0:
1571 # if found HII type PCD then insert to right of UnicodeIndex
1572 HiiPcdArray
.append(Pcd
)
1574 OtherPcdArray
.append(Pcd
)
1575 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
1576 VpdPcdDict
[(Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
)] = Pcd
1578 PlatformPcds
= self
._PlatformPcds
.keys()
1581 # Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.
1583 for PcdKey
in PlatformPcds
:
1584 Pcd
= self
._PlatformPcds
[PcdKey
]
1585 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
] and \
1586 PcdKey
in VpdPcdDict
:
1587 Pcd
= VpdPcdDict
[PcdKey
]
1588 for (SkuName
,Sku
) in Pcd
.SkuInfoList
.items():
1589 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1590 PcdValue
= Sku
.DefaultValue
1592 PcdValue
= Pcd
.DefaultValue
1593 if Sku
.VpdOffset
!= '*':
1594 if PcdValue
.startswith("{"):
1596 elif PcdValue
.startswith("L"):
1601 VpdOffset
= int(Sku
.VpdOffset
)
1604 VpdOffset
= int(Sku
.VpdOffset
, 16)
1606 EdkLogger
.error("build", FORMAT_INVALID
, "Invalid offset value %s for PCD %s.%s." % (Sku
.VpdOffset
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
1607 if VpdOffset
% Alignment
!= 0:
1608 if PcdValue
.startswith("{"):
1609 EdkLogger
.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
), File
=self
.MetaFile
)
1611 EdkLogger
.error("build", FORMAT_INVALID
, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
, Alignment
))
1612 VpdFile
.Add(Pcd
, Sku
.VpdOffset
)
1613 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
1614 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== "*":
1615 NeedProcessVpdMapFile
= True
1616 if self
.Platform
.VpdToolGuid
== None or self
.Platform
.VpdToolGuid
== '':
1617 EdkLogger
.error("Build", FILE_NOT_FOUND
, \
1618 "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.")
1622 # Fix the PCDs define in VPD PCD section that never referenced by module.
1623 # An example is PCD for signature usage.
1625 for DscPcd
in PlatformPcds
:
1626 DscPcdEntry
= self
._PlatformPcds
[DscPcd
]
1627 if DscPcdEntry
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
1628 if not (self
.Platform
.VpdToolGuid
== None or self
.Platform
.VpdToolGuid
== ''):
1630 for VpdPcd
in VpdFile
._VpdArray
.keys():
1631 # This PCD has been referenced by module
1632 if (VpdPcd
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
1633 (VpdPcd
.TokenCName
== DscPcdEntry
.TokenCName
):
1636 # Not found, it should be signature
1638 # just pick the a value to determine whether is unicode string type
1639 for (SkuName
,Sku
) in DscPcdEntry
.SkuInfoList
.items():
1640 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1642 # Need to iterate DEC pcd information to get the value & datumtype
1643 for eachDec
in self
.PackageList
:
1644 for DecPcd
in eachDec
.Pcds
:
1645 DecPcdEntry
= eachDec
.Pcds
[DecPcd
]
1646 if (DecPcdEntry
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
1647 (DecPcdEntry
.TokenCName
== DscPcdEntry
.TokenCName
):
1648 # Print warning message to let the developer make a determine.
1649 EdkLogger
.warn("build", "Unreferenced vpd pcd used!",
1650 File
=self
.MetaFile
, \
1651 ExtraData
= "PCD: %s.%s used in the DSC file %s is unreferenced." \
1652 %(DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
, self
.Platform
.MetaFile
.Path
))
1654 DscPcdEntry
.DatumType
= DecPcdEntry
.DatumType
1655 DscPcdEntry
.DefaultValue
= DecPcdEntry
.DefaultValue
1656 DscPcdEntry
.TokenValue
= DecPcdEntry
.TokenValue
1657 DscPcdEntry
.TokenSpaceGuidValue
= eachDec
.Guids
[DecPcdEntry
.TokenSpaceGuidCName
]
1658 # Only fix the value while no value provided in DSC file.
1659 if (Sku
.DefaultValue
== "" or Sku
.DefaultValue
==None):
1660 DscPcdEntry
.SkuInfoList
[DscPcdEntry
.SkuInfoList
.keys()[0]].DefaultValue
= DecPcdEntry
.DefaultValue
1662 if DscPcdEntry
not in self
._DynamicPcdList
:
1663 self
._DynamicPcdList
.append(DscPcdEntry
)
1664 # Sku = DscPcdEntry.SkuInfoList[DscPcdEntry.SkuInfoList.keys()[0]]
1665 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1666 PcdValue
= Sku
.DefaultValue
1668 PcdValue
= DscPcdEntry
.DefaultValue
1669 if Sku
.VpdOffset
!= '*':
1670 if PcdValue
.startswith("{"):
1672 elif PcdValue
.startswith("L"):
1677 VpdOffset
= int(Sku
.VpdOffset
)
1680 VpdOffset
= int(Sku
.VpdOffset
, 16)
1682 EdkLogger
.error("build", FORMAT_INVALID
, "Invalid offset value %s for PCD %s.%s." % (Sku
.VpdOffset
, DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
))
1683 if VpdOffset
% Alignment
!= 0:
1684 if PcdValue
.startswith("{"):
1685 EdkLogger
.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
), File
=self
.MetaFile
)
1687 EdkLogger
.error("build", FORMAT_INVALID
, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
, Alignment
))
1688 VpdFile
.Add(DscPcdEntry
, Sku
.VpdOffset
)
1689 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== "*":
1690 NeedProcessVpdMapFile
= True
1691 if DscPcdEntry
.DatumType
== 'VOID*' and PcdValue
.startswith("L"):
1692 UnicodePcdArray
.append(DscPcdEntry
)
1693 elif len(Sku
.VariableName
) > 0:
1694 HiiPcdArray
.append(DscPcdEntry
)
1696 OtherPcdArray
.append(DscPcdEntry
)
1698 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
1702 if (self
.Platform
.FlashDefinition
== None or self
.Platform
.FlashDefinition
== '') and \
1703 VpdFile
.GetCount() != 0:
1704 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
,
1705 "Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD." % str(self
.Platform
.MetaFile
))
1707 if VpdFile
.GetCount() != 0:
1708 FvPath
= os
.path
.join(self
.BuildDir
, "FV")
1709 if not os
.path
.exists(FvPath
):
1713 EdkLogger
.error("build", FILE_WRITE_FAILURE
, "Fail to create FV folder under %s" % self
.BuildDir
)
1715 VpdFilePath
= os
.path
.join(FvPath
, "%s.txt" % self
.Platform
.VpdToolGuid
)
1717 if VpdFile
.Write(VpdFilePath
):
1718 # retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.
1720 for ToolDef
in self
.ToolDefinition
.values():
1721 if ToolDef
.has_key("GUID") and ToolDef
["GUID"] == self
.Platform
.VpdToolGuid
:
1722 if not ToolDef
.has_key("PATH"):
1723 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
, "PATH attribute was not provided for BPDG guid tool %s in tools_def.txt" % self
.Platform
.VpdToolGuid
)
1724 BPDGToolName
= ToolDef
["PATH"]
1726 # Call third party GUID BPDG tool.
1727 if BPDGToolName
!= None:
1728 VpdInfoFile
.CallExtenalBPDGTool(BPDGToolName
, VpdFilePath
)
1730 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.")
1732 # Process VPD map file generated by third party BPDG tool
1733 if NeedProcessVpdMapFile
:
1734 VpdMapFilePath
= os
.path
.join(self
.BuildDir
, "FV", "%s.map" % self
.Platform
.VpdToolGuid
)
1735 if os
.path
.exists(VpdMapFilePath
):
1736 VpdFile
.Read(VpdMapFilePath
)
1739 for Pcd
in self
._DynamicPcdList
:
1740 # just pick the a value to determine whether is unicode string type
1742 for (SkuName
,Sku
) in Pcd
.SkuInfoList
.items():
1743 if Sku
.VpdOffset
== "*":
1744 Sku
.VpdOffset
= VpdFile
.GetOffset(Pcd
)[i
].strip()
1747 EdkLogger
.error("build", FILE_READ_FAILURE
, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath
)
1749 # Delete the DynamicPcdList At the last time enter into this function
1750 del self
._DynamicPcdList
[:]
1751 self
._DynamicPcdList
.extend(UnicodePcdArray
)
1752 self
._DynamicPcdList
.extend(HiiPcdArray
)
1753 self
._DynamicPcdList
.extend(OtherPcdArray
)
1754 self
.AllPcdList
= self
._NonDynamicPcdList
+ self
._DynamicPcdList
1756 ## Return the platform build data object
1757 def _GetPlatform(self
):
1758 if self
._Platform
== None:
1759 self
._Platform
= self
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1760 return self
._Platform
1762 ## Return platform name
1764 return self
.Platform
.PlatformName
1766 ## Return the meta file GUID
1768 return self
.Platform
.Guid
1770 ## Return the platform version
1771 def _GetVersion(self
):
1772 return self
.Platform
.Version
1774 ## Return the FDF file name
1775 def _GetFdfFile(self
):
1776 if self
._FdfFile
== None:
1777 if self
.Workspace
.FdfFile
!= "":
1778 self
._FdfFile
= mws
.join(self
.WorkspaceDir
, self
.Workspace
.FdfFile
)
1781 return self
._FdfFile
1783 ## Return the build output directory platform specifies
1784 def _GetOutputDir(self
):
1785 return self
.Platform
.OutputDirectory
1787 ## Return the directory to store all intermediate and final files built
1788 def _GetBuildDir(self
):
1789 if self
._BuildDir
== None:
1790 if os
.path
.isabs(self
.OutputDir
):
1791 self
._BuildDir
= path
.join(
1792 path
.abspath(self
.OutputDir
),
1793 self
.BuildTarget
+ "_" + self
.ToolChain
,
1796 self
._BuildDir
= path
.join(
1799 self
.BuildTarget
+ "_" + self
.ToolChain
,
1801 return self
._BuildDir
1803 ## Return directory of platform makefile
1805 # @retval string Makefile directory
1807 def _GetMakeFileDir(self
):
1808 if self
._MakeFileDir
== None:
1809 self
._MakeFileDir
= path
.join(self
.BuildDir
, self
.Arch
)
1810 return self
._MakeFileDir
1812 ## Return build command string
1814 # @retval string Build command string
1816 def _GetBuildCommand(self
):
1817 if self
._BuildCommand
== None:
1818 self
._BuildCommand
= []
1819 if "MAKE" in self
.ToolDefinition
and "PATH" in self
.ToolDefinition
["MAKE"]:
1820 self
._BuildCommand
+= SplitOption(self
.ToolDefinition
["MAKE"]["PATH"])
1821 if "FLAGS" in self
.ToolDefinition
["MAKE"]:
1822 NewOption
= self
.ToolDefinition
["MAKE"]["FLAGS"].strip()
1824 self
._BuildCommand
+= SplitOption(NewOption
)
1825 return self
._BuildCommand
1827 ## Get tool chain definition
1829 # Get each tool defition for given tool chain from tools_def.txt and platform
1831 def _GetToolDefinition(self
):
1832 if self
._ToolDefinitions
== None:
1833 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDictionary
1834 if TAB_TOD_DEFINES_COMMAND_TYPE
not in self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
:
1835 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
, "No tools found in configuration",
1836 ExtraData
="[%s]" % self
.MetaFile
)
1837 self
._ToolDefinitions
= {}
1839 for Def
in ToolDefinition
:
1840 Target
, Tag
, Arch
, Tool
, Attr
= Def
.split("_")
1841 if Target
!= self
.BuildTarget
or Tag
!= self
.ToolChain
or Arch
!= self
.Arch
:
1844 Value
= ToolDefinition
[Def
]
1845 # don't record the DLL
1847 DllPathList
.add(Value
)
1850 if Tool
not in self
._ToolDefinitions
:
1851 self
._ToolDefinitions
[Tool
] = {}
1852 self
._ToolDefinitions
[Tool
][Attr
] = Value
1856 if GlobalData
.gOptions
.SilentMode
and "MAKE" in self
._ToolDefinitions
:
1857 if "FLAGS" not in self
._ToolDefinitions
["MAKE"]:
1858 self
._ToolDefinitions
["MAKE"]["FLAGS"] = ""
1859 self
._ToolDefinitions
["MAKE"]["FLAGS"] += " -s"
1861 for Tool
in self
._ToolDefinitions
:
1862 for Attr
in self
._ToolDefinitions
[Tool
]:
1863 Value
= self
._ToolDefinitions
[Tool
][Attr
]
1864 if Tool
in self
.BuildOption
and Attr
in self
.BuildOption
[Tool
]:
1865 # check if override is indicated
1866 if self
.BuildOption
[Tool
][Attr
].startswith('='):
1867 Value
= self
.BuildOption
[Tool
][Attr
][1:]
1870 Value
+= " " + self
.BuildOption
[Tool
][Attr
]
1872 Value
= self
.BuildOption
[Tool
][Attr
]
1875 # Don't put MAKE definition in the file
1879 ToolsDef
+= "%s = %s\n" % (Tool
, Value
)
1881 # Don't put MAKE definition in the file
1886 ToolsDef
+= "%s_%s = %s\n" % (Tool
, Attr
, Value
)
1889 SaveFileOnChange(self
.ToolDefinitionFile
, ToolsDef
)
1890 for DllPath
in DllPathList
:
1891 os
.environ
["PATH"] = DllPath
+ os
.pathsep
+ os
.environ
["PATH"]
1892 os
.environ
["MAKE_FLAGS"] = MakeFlags
1894 return self
._ToolDefinitions
1896 ## Return the paths of tools
1897 def _GetToolDefFile(self
):
1898 if self
._ToolDefFile
== None:
1899 self
._ToolDefFile
= os
.path
.join(self
.MakeFileDir
, "TOOLS_DEF." + self
.Arch
)
1900 return self
._ToolDefFile
1902 ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
1903 def _GetToolChainFamily(self
):
1904 if self
._ToolChainFamily
== None:
1905 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
1906 if TAB_TOD_DEFINES_FAMILY
not in ToolDefinition \
1907 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_FAMILY
] \
1908 or not ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]:
1909 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1911 self
._ToolChainFamily
= "MSFT"
1913 self
._ToolChainFamily
= ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]
1914 return self
._ToolChainFamily
1916 def _GetBuildRuleFamily(self
):
1917 if self
._BuildRuleFamily
== None:
1918 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
1919 if TAB_TOD_DEFINES_BUILDRULEFAMILY
not in ToolDefinition \
1920 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
] \
1921 or not ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]:
1922 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1924 self
._BuildRuleFamily
= "MSFT"
1926 self
._BuildRuleFamily
= ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]
1927 return self
._BuildRuleFamily
1929 ## Return the build options specific for all modules in this platform
1930 def _GetBuildOptions(self
):
1931 if self
._BuildOption
== None:
1932 self
._BuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
)
1933 return self
._BuildOption
1935 ## Return the build options specific for EDK modules in this platform
1936 def _GetEdkBuildOptions(self
):
1937 if self
._EdkBuildOption
== None:
1938 self
._EdkBuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDK_NAME
)
1939 return self
._EdkBuildOption
1941 ## Return the build options specific for EDKII modules in this platform
1942 def _GetEdkIIBuildOptions(self
):
1943 if self
._EdkIIBuildOption
== None:
1944 self
._EdkIIBuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDKII_NAME
)
1945 return self
._EdkIIBuildOption
1947 ## Parse build_rule.txt in Conf Directory.
1949 # @retval BuildRule object
1951 def _GetBuildRule(self
):
1952 if self
._BuildRule
== None:
1953 BuildRuleFile
= None
1954 if TAB_TAT_DEFINES_BUILD_RULE_CONF
in self
.Workspace
.TargetTxt
.TargetTxtDictionary
:
1955 BuildRuleFile
= self
.Workspace
.TargetTxt
.TargetTxtDictionary
[TAB_TAT_DEFINES_BUILD_RULE_CONF
]
1956 if BuildRuleFile
in [None, '']:
1957 BuildRuleFile
= gDefaultBuildRuleFile
1958 self
._BuildRule
= BuildRule(BuildRuleFile
)
1959 if self
._BuildRule
._FileVersion
== "":
1960 self
._BuildRule
._FileVersion
= AutoGenReqBuildRuleVerNum
1962 if self
._BuildRule
._FileVersion
< AutoGenReqBuildRuleVerNum
:
1963 # If Build Rule's version is less than the version number required by the tools, halting the build.
1964 EdkLogger
.error("build", AUTOGEN_ERROR
,
1965 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])"\
1966 % (self
._BuildRule
._FileVersion
, AutoGenReqBuildRuleVerNum
))
1968 return self
._BuildRule
1970 ## Summarize the packages used by modules in this platform
1971 def _GetPackageList(self
):
1972 if self
._PackageList
== None:
1973 self
._PackageList
= set()
1974 for La
in self
.LibraryAutoGenList
:
1975 self
._PackageList
.update(La
.DependentPackageList
)
1976 for Ma
in self
.ModuleAutoGenList
:
1977 self
._PackageList
.update(Ma
.DependentPackageList
)
1978 #Collect package set information from INF of FDF
1980 for ModuleFile
in self
._AsBuildModuleList
:
1981 if ModuleFile
in self
.Platform
.Modules
:
1983 ModuleData
= self
.BuildDatabase
[ModuleFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1984 PkgSet
.update(ModuleData
.Packages
)
1985 self
._PackageList
= list(self
._PackageList
) + list (PkgSet
)
1986 return self
._PackageList
1988 def _GetNonDynamicPcdDict(self
):
1989 if self
._NonDynamicPcdDict
:
1990 return self
._NonDynamicPcdDict
1991 for Pcd
in self
.NonDynamicPcdList
:
1992 self
._NonDynamicPcdDict
[(Pcd
.TokenCName
,Pcd
.TokenSpaceGuidCName
)] = Pcd
1993 return self
._NonDynamicPcdDict
1995 ## Get list of non-dynamic PCDs
1996 def _GetNonDynamicPcdList(self
):
1997 if self
._NonDynamicPcdList
== None:
1998 self
.CollectPlatformDynamicPcds()
1999 return self
._NonDynamicPcdList
2001 ## Get list of dynamic PCDs
2002 def _GetDynamicPcdList(self
):
2003 if self
._DynamicPcdList
== None:
2004 self
.CollectPlatformDynamicPcds()
2005 return self
._DynamicPcdList
2007 ## Generate Token Number for all PCD
2008 def _GetPcdTokenNumbers(self
):
2009 if self
._PcdTokenNumber
== None:
2010 self
._PcdTokenNumber
= sdict()
2013 # Make the Dynamic and DynamicEx PCD use within different TokenNumber area.
2017 # TokenNumber 0 ~ 10
2019 # TokeNumber 11 ~ 20
2021 for Pcd
in self
.DynamicPcdList
:
2022 if Pcd
.Phase
== "PEI":
2023 if Pcd
.Type
in ["Dynamic", "DynamicDefault", "DynamicVpd", "DynamicHii"]:
2024 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2025 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2028 for Pcd
in self
.DynamicPcdList
:
2029 if Pcd
.Phase
== "PEI":
2030 if Pcd
.Type
in ["DynamicEx", "DynamicExDefault", "DynamicExVpd", "DynamicExHii"]:
2031 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2032 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2035 for Pcd
in self
.DynamicPcdList
:
2036 if Pcd
.Phase
== "DXE":
2037 if Pcd
.Type
in ["Dynamic", "DynamicDefault", "DynamicVpd", "DynamicHii"]:
2038 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2039 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2042 for Pcd
in self
.DynamicPcdList
:
2043 if Pcd
.Phase
== "DXE":
2044 if Pcd
.Type
in ["DynamicEx", "DynamicExDefault", "DynamicExVpd", "DynamicExHii"]:
2045 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2046 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2049 for Pcd
in self
.NonDynamicPcdList
:
2050 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2052 return self
._PcdTokenNumber
2054 ## Summarize ModuleAutoGen objects of all modules/libraries to be built for this platform
2055 def _GetAutoGenObjectList(self
):
2056 self
._ModuleAutoGenList
= []
2057 self
._LibraryAutoGenList
= []
2058 for ModuleFile
in self
.Platform
.Modules
:
2067 if Ma
not in self
._ModuleAutoGenList
:
2068 self
._ModuleAutoGenList
.append(Ma
)
2069 for La
in Ma
.LibraryAutoGenList
:
2070 if La
not in self
._LibraryAutoGenList
:
2071 self
._LibraryAutoGenList
.append(La
)
2072 if Ma
not in La
._ReferenceModules
:
2073 La
._ReferenceModules
.append(Ma
)
2075 ## Summarize ModuleAutoGen objects of all modules to be built for this platform
2076 def _GetModuleAutoGenList(self
):
2077 if self
._ModuleAutoGenList
== None:
2078 self
._GetAutoGenObjectList
()
2079 return self
._ModuleAutoGenList
2081 ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
2082 def _GetLibraryAutoGenList(self
):
2083 if self
._LibraryAutoGenList
== None:
2084 self
._GetAutoGenObjectList
()
2085 return self
._LibraryAutoGenList
2087 ## Test if a module is supported by the platform
2089 # An error will be raised directly if the module or its arch is not supported
2090 # by the platform or current configuration
2092 def ValidModule(self
, Module
):
2093 return Module
in self
.Platform
.Modules
or Module
in self
.Platform
.LibraryInstances \
2094 or Module
in self
._AsBuildModuleList
2096 ## Resolve the library classes in a module to library instances
2098 # This method will not only resolve library classes but also sort the library
2099 # instances according to the dependency-ship.
2101 # @param Module The module from which the library classes will be resolved
2103 # @retval library_list List of library instances sorted
2105 def ApplyLibraryInstance(self
, Module
):
2106 # Cover the case that the binary INF file is list in the FDF file but not DSC file, return empty list directly
2107 if str(Module
) not in self
.Platform
.Modules
:
2110 ModuleType
= Module
.ModuleType
2112 # for overridding library instances with module specific setting
2113 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
2115 # add forced library instances (specified under LibraryClasses sections)
2117 # If a module has a MODULE_TYPE of USER_DEFINED,
2118 # do not link in NULL library class instances from the global [LibraryClasses.*] sections.
2120 if Module
.ModuleType
!= SUP_MODULE_USER_DEFINED
:
2121 for LibraryClass
in self
.Platform
.LibraryClasses
.GetKeys():
2122 if LibraryClass
.startswith("NULL") and self
.Platform
.LibraryClasses
[LibraryClass
, Module
.ModuleType
]:
2123 Module
.LibraryClasses
[LibraryClass
] = self
.Platform
.LibraryClasses
[LibraryClass
, Module
.ModuleType
]
2125 # add forced library instances (specified in module overrides)
2126 for LibraryClass
in PlatformModule
.LibraryClasses
:
2127 if LibraryClass
.startswith("NULL"):
2128 Module
.LibraryClasses
[LibraryClass
] = PlatformModule
.LibraryClasses
[LibraryClass
]
2131 LibraryConsumerList
= [Module
]
2133 ConsumedByList
= sdict()
2134 LibraryInstance
= sdict()
2136 EdkLogger
.verbose("")
2137 EdkLogger
.verbose("Library instances of module [%s] [%s]:" % (str(Module
), self
.Arch
))
2138 while len(LibraryConsumerList
) > 0:
2139 M
= LibraryConsumerList
.pop()
2140 for LibraryClassName
in M
.LibraryClasses
:
2141 if LibraryClassName
not in LibraryInstance
:
2142 # override library instance for this module
2143 if LibraryClassName
in PlatformModule
.LibraryClasses
:
2144 LibraryPath
= PlatformModule
.LibraryClasses
[LibraryClassName
]
2146 LibraryPath
= self
.Platform
.LibraryClasses
[LibraryClassName
, ModuleType
]
2147 if LibraryPath
== None or LibraryPath
== "":
2148 LibraryPath
= M
.LibraryClasses
[LibraryClassName
]
2149 if LibraryPath
== None or LibraryPath
== "":
2150 EdkLogger
.error("build", RESOURCE_NOT_AVAILABLE
,
2151 "Instance of library class [%s] is not found" % LibraryClassName
,
2153 ExtraData
="in [%s] [%s]\n\tconsumed by module [%s]" % (str(M
), self
.Arch
, str(Module
)))
2155 LibraryModule
= self
.BuildDatabase
[LibraryPath
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
2156 # for those forced library instance (NULL library), add a fake library class
2157 if LibraryClassName
.startswith("NULL"):
2158 LibraryModule
.LibraryClass
.append(LibraryClassObject(LibraryClassName
, [ModuleType
]))
2159 elif LibraryModule
.LibraryClass
== None \
2160 or len(LibraryModule
.LibraryClass
) == 0 \
2161 or (ModuleType
!= 'USER_DEFINED'
2162 and ModuleType
not in LibraryModule
.LibraryClass
[0].SupModList
):
2163 # only USER_DEFINED can link against any library instance despite of its SupModList
2164 EdkLogger
.error("build", OPTION_MISSING
,
2165 "Module type [%s] is not supported by library instance [%s]" \
2166 % (ModuleType
, LibraryPath
), File
=self
.MetaFile
,
2167 ExtraData
="consumed by [%s]" % str(Module
))
2169 LibraryInstance
[LibraryClassName
] = LibraryModule
2170 LibraryConsumerList
.append(LibraryModule
)
2171 EdkLogger
.verbose("\t" + str(LibraryClassName
) + " : " + str(LibraryModule
))
2173 LibraryModule
= LibraryInstance
[LibraryClassName
]
2175 if LibraryModule
== None:
2178 if LibraryModule
.ConstructorList
!= [] and LibraryModule
not in Constructor
:
2179 Constructor
.append(LibraryModule
)
2181 if LibraryModule
not in ConsumedByList
:
2182 ConsumedByList
[LibraryModule
] = []
2183 # don't add current module itself to consumer list
2185 if M
in ConsumedByList
[LibraryModule
]:
2187 ConsumedByList
[LibraryModule
].append(M
)
2189 # Initialize the sorted output list to the empty set
2191 SortedLibraryList
= []
2193 # Q <- Set of all nodes with no incoming edges
2195 LibraryList
= [] #LibraryInstance.values()
2197 for LibraryClassName
in LibraryInstance
:
2198 M
= LibraryInstance
[LibraryClassName
]
2199 LibraryList
.append(M
)
2200 if ConsumedByList
[M
] == []:
2204 # start the DAG algorithm
2208 while Q
== [] and EdgeRemoved
:
2210 # for each node Item with a Constructor
2211 for Item
in LibraryList
:
2212 if Item
not in Constructor
:
2214 # for each Node without a constructor with an edge e from Item to Node
2215 for Node
in ConsumedByList
[Item
]:
2216 if Node
in Constructor
:
2218 # remove edge e from the graph if Node has no constructor
2219 ConsumedByList
[Item
].remove(Node
)
2221 if ConsumedByList
[Item
] == []:
2222 # insert Item into Q
2227 # DAG is done if there's no more incoming edge for all nodes
2231 # remove node from Q
2234 SortedLibraryList
.append(Node
)
2236 # for each node Item with an edge e from Node to Item do
2237 for Item
in LibraryList
:
2238 if Node
not in ConsumedByList
[Item
]:
2240 # remove edge e from the graph
2241 ConsumedByList
[Item
].remove(Node
)
2243 if ConsumedByList
[Item
] != []:
2245 # insert Item into Q, if Item has no other incoming edges
2249 # if any remaining node Item in the graph has a constructor and an incoming edge, then the graph has a cycle
2251 for Item
in LibraryList
:
2252 if ConsumedByList
[Item
] != [] and Item
in Constructor
and len(Constructor
) > 1:
2253 ErrorMessage
= "\tconsumed by " + "\n\tconsumed by ".join([str(L
) for L
in ConsumedByList
[Item
]])
2254 EdkLogger
.error("build", BUILD_ERROR
, 'Library [%s] with constructors has a cycle' % str(Item
),
2255 ExtraData
=ErrorMessage
, File
=self
.MetaFile
)
2256 if Item
not in SortedLibraryList
:
2257 SortedLibraryList
.append(Item
)
2260 # Build the list of constructor and destructir names
2261 # The DAG Topo sort produces the destructor order, so the list of constructors must generated in the reverse order
2263 SortedLibraryList
.reverse()
2264 return SortedLibraryList
2267 ## Override PCD setting (type, value, ...)
2269 # @param ToPcd The PCD to be overrided
2270 # @param FromPcd The PCD overrideing from
2272 def _OverridePcd(self
, ToPcd
, FromPcd
, Module
=""):
2274 # in case there's PCDs coming from FDF file, which have no type given.
2275 # at this point, ToPcd.Type has the type found from dependent
2278 TokenCName
= ToPcd
.TokenCName
2279 for PcdItem
in GlobalData
.MixedPcd
:
2280 if (ToPcd
.TokenCName
, ToPcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
2281 TokenCName
= PcdItem
[0]
2284 if GlobalData
.BuildOptionPcd
:
2285 for pcd
in GlobalData
.BuildOptionPcd
:
2286 if (FromPcd
.TokenSpaceGuidCName
, FromPcd
.TokenCName
) == (pcd
[0], pcd
[1]):
2287 FromPcd
.DefaultValue
= pcd
[2]
2289 if ToPcd
.Pending
and FromPcd
.Type
not in [None, '']:
2290 ToPcd
.Type
= FromPcd
.Type
2291 elif (ToPcd
.Type
not in [None, '']) and (FromPcd
.Type
not in [None, ''])\
2292 and (ToPcd
.Type
!= FromPcd
.Type
) and (ToPcd
.Type
in FromPcd
.Type
):
2293 if ToPcd
.Type
.strip() == "DynamicEx":
2294 ToPcd
.Type
= FromPcd
.Type
2295 elif ToPcd
.Type
not in [None, ''] and FromPcd
.Type
not in [None, ''] \
2296 and ToPcd
.Type
!= FromPcd
.Type
:
2297 EdkLogger
.error("build", OPTION_CONFLICT
, "Mismatched PCD type",
2298 ExtraData
="%s.%s is defined as [%s] in module %s, but as [%s] in platform."\
2299 % (ToPcd
.TokenSpaceGuidCName
, TokenCName
,
2300 ToPcd
.Type
, Module
, FromPcd
.Type
),
2303 if FromPcd
.MaxDatumSize
not in [None, '']:
2304 ToPcd
.MaxDatumSize
= FromPcd
.MaxDatumSize
2305 if FromPcd
.DefaultValue
not in [None, '']:
2306 ToPcd
.DefaultValue
= FromPcd
.DefaultValue
2307 if FromPcd
.TokenValue
not in [None, '']:
2308 ToPcd
.TokenValue
= FromPcd
.TokenValue
2309 if FromPcd
.MaxDatumSize
not in [None, '']:
2310 ToPcd
.MaxDatumSize
= FromPcd
.MaxDatumSize
2311 if FromPcd
.DatumType
not in [None, '']:
2312 ToPcd
.DatumType
= FromPcd
.DatumType
2313 if FromPcd
.SkuInfoList
not in [None, '', []]:
2314 ToPcd
.SkuInfoList
= FromPcd
.SkuInfoList
2316 # check the validation of datum
2317 IsValid
, Cause
= CheckPcdDatum(ToPcd
.DatumType
, ToPcd
.DefaultValue
)
2319 EdkLogger
.error('build', FORMAT_INVALID
, Cause
, File
=self
.MetaFile
,
2320 ExtraData
="%s.%s" % (ToPcd
.TokenSpaceGuidCName
, TokenCName
))
2321 ToPcd
.validateranges
= FromPcd
.validateranges
2322 ToPcd
.validlists
= FromPcd
.validlists
2323 ToPcd
.expressions
= FromPcd
.expressions
2325 if ToPcd
.DatumType
== "VOID*" and ToPcd
.MaxDatumSize
in ['', None]:
2326 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "No MaxDatumSize specified for PCD %s.%s" \
2327 % (ToPcd
.TokenSpaceGuidCName
, TokenCName
))
2328 Value
= ToPcd
.DefaultValue
2329 if Value
in [None, '']:
2330 ToPcd
.MaxDatumSize
= '1'
2331 elif Value
[0] == 'L':
2332 ToPcd
.MaxDatumSize
= str((len(Value
) - 2) * 2)
2333 elif Value
[0] == '{':
2334 ToPcd
.MaxDatumSize
= str(len(Value
.split(',')))
2336 ToPcd
.MaxDatumSize
= str(len(Value
) - 1)
2338 # apply default SKU for dynamic PCDS if specified one is not available
2339 if (ToPcd
.Type
in PCD_DYNAMIC_TYPE_LIST
or ToPcd
.Type
in PCD_DYNAMIC_EX_TYPE_LIST
) \
2340 and ToPcd
.SkuInfoList
in [None, {}, '']:
2341 if self
.Platform
.SkuName
in self
.Platform
.SkuIds
:
2342 SkuName
= self
.Platform
.SkuName
2345 ToPcd
.SkuInfoList
= {
2346 SkuName
: SkuInfoClass(SkuName
, self
.Platform
.SkuIds
[SkuName
], '', '', '', '', '', ToPcd
.DefaultValue
)
2349 ## Apply PCD setting defined platform to a module
2351 # @param Module The module from which the PCD setting will be overrided
2353 # @retval PCD_list The list PCDs with settings from platform
2355 def ApplyPcdSetting(self
, Module
, Pcds
):
2356 # for each PCD in module
2357 for Name
, Guid
in Pcds
:
2358 PcdInModule
= Pcds
[Name
, Guid
]
2359 # find out the PCD setting in platform
2360 if (Name
, Guid
) in self
.Platform
.Pcds
:
2361 PcdInPlatform
= self
.Platform
.Pcds
[Name
, Guid
]
2363 PcdInPlatform
= None
2364 # then override the settings if any
2365 self
._OverridePcd
(PcdInModule
, PcdInPlatform
, Module
)
2366 # resolve the VariableGuid value
2367 for SkuId
in PcdInModule
.SkuInfoList
:
2368 Sku
= PcdInModule
.SkuInfoList
[SkuId
]
2369 if Sku
.VariableGuid
== '': continue
2370 Sku
.VariableGuidValue
= GuidValue(Sku
.VariableGuid
, self
.PackageList
, self
.MetaFile
.Path
)
2371 if Sku
.VariableGuidValue
== None:
2372 PackageList
= "\n\t".join([str(P
) for P
in self
.PackageList
])
2375 RESOURCE_NOT_AVAILABLE
,
2376 "Value of GUID [%s] is not found in" % Sku
.VariableGuid
,
2377 ExtraData
=PackageList
+ "\n\t(used with %s.%s from module %s)" \
2378 % (Guid
, Name
, str(Module
)),
2382 # override PCD settings with module specific setting
2383 if Module
in self
.Platform
.Modules
:
2384 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
2385 for Key
in PlatformModule
.Pcds
:
2390 elif Key
in GlobalData
.MixedPcd
:
2391 for PcdItem
in GlobalData
.MixedPcd
[Key
]:
2393 ToPcd
= Pcds
[PcdItem
]
2397 self
._OverridePcd
(ToPcd
, PlatformModule
.Pcds
[Key
], Module
)
2398 return Pcds
.values()
2400 ## Resolve library names to library modules
2402 # (for Edk.x modules)
2404 # @param Module The module from which the library names will be resolved
2406 # @retval library_list The list of library modules
2408 def ResolveLibraryReference(self
, Module
):
2409 EdkLogger
.verbose("")
2410 EdkLogger
.verbose("Library instances of module [%s] [%s]:" % (str(Module
), self
.Arch
))
2411 LibraryConsumerList
= [Module
]
2413 # "CompilerStub" is a must for Edk modules
2414 if Module
.Libraries
:
2415 Module
.Libraries
.append("CompilerStub")
2417 while len(LibraryConsumerList
) > 0:
2418 M
= LibraryConsumerList
.pop()
2419 for LibraryName
in M
.Libraries
:
2420 Library
= self
.Platform
.LibraryClasses
[LibraryName
, ':dummy:']
2422 for Key
in self
.Platform
.LibraryClasses
.data
.keys():
2423 if LibraryName
.upper() == Key
.upper():
2424 Library
= self
.Platform
.LibraryClasses
[Key
, ':dummy:']
2427 EdkLogger
.warn("build", "Library [%s] is not found" % LibraryName
, File
=str(M
),
2428 ExtraData
="\t%s [%s]" % (str(Module
), self
.Arch
))
2431 if Library
not in LibraryList
:
2432 LibraryList
.append(Library
)
2433 LibraryConsumerList
.append(Library
)
2434 EdkLogger
.verbose("\t" + LibraryName
+ " : " + str(Library
) + ' ' + str(type(Library
)))
2437 ## Calculate the priority value of the build option
2439 # @param Key Build option definition contain: TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
2441 # @retval Value Priority value based on the priority list.
2443 def CalculatePriorityValue(self
, Key
):
2444 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
.split('_')
2445 PriorityValue
= 0x11111
2447 PriorityValue
&= 0x01111
2448 if ToolChain
== "*":
2449 PriorityValue
&= 0x10111
2451 PriorityValue
&= 0x11011
2452 if CommandType
== "*":
2453 PriorityValue
&= 0x11101
2455 PriorityValue
&= 0x11110
2457 return self
.PrioList
["0x%0.5x" % PriorityValue
]
2460 ## Expand * in build option key
2462 # @param Options Options to be expanded
2464 # @retval options Options expanded
2466 def _ExpandBuildOption(self
, Options
, ModuleStyle
=None):
2473 # Construct a list contain the build options which need override.
2477 # Key[0] -- tool family
2478 # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
2480 if (Key
[0] == self
.BuildRuleFamily
and
2481 (ModuleStyle
== None or len(Key
) < 3 or (len(Key
) > 2 and Key
[2] == ModuleStyle
))):
2482 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
[1].split('_')
2483 if Target
== self
.BuildTarget
or Target
== "*":
2484 if ToolChain
== self
.ToolChain
or ToolChain
== "*":
2485 if Arch
== self
.Arch
or Arch
== "*":
2486 if Options
[Key
].startswith("="):
2487 if OverrideList
.get(Key
[1]) != None:
2488 OverrideList
.pop(Key
[1])
2489 OverrideList
[Key
[1]] = Options
[Key
]
2492 # Use the highest priority value.
2494 if (len(OverrideList
) >= 2):
2495 KeyList
= OverrideList
.keys()
2496 for Index
in range(len(KeyList
)):
2497 NowKey
= KeyList
[Index
]
2498 Target1
, ToolChain1
, Arch1
, CommandType1
, Attr1
= NowKey
.split("_")
2499 for Index1
in range(len(KeyList
) - Index
- 1):
2500 NextKey
= KeyList
[Index1
+ Index
+ 1]
2502 # Compare two Key, if one is included by another, choose the higher priority one
2504 Target2
, ToolChain2
, Arch2
, CommandType2
, Attr2
= NextKey
.split("_")
2505 if Target1
== Target2
or Target1
== "*" or Target2
== "*":
2506 if ToolChain1
== ToolChain2
or ToolChain1
== "*" or ToolChain2
== "*":
2507 if Arch1
== Arch2
or Arch1
== "*" or Arch2
== "*":
2508 if CommandType1
== CommandType2
or CommandType1
== "*" or CommandType2
== "*":
2509 if Attr1
== Attr2
or Attr1
== "*" or Attr2
== "*":
2510 if self
.CalculatePriorityValue(NowKey
) > self
.CalculatePriorityValue(NextKey
):
2511 if Options
.get((self
.BuildRuleFamily
, NextKey
)) != None:
2512 Options
.pop((self
.BuildRuleFamily
, NextKey
))
2514 if Options
.get((self
.BuildRuleFamily
, NowKey
)) != None:
2515 Options
.pop((self
.BuildRuleFamily
, NowKey
))
2518 if ModuleStyle
!= None and len (Key
) > 2:
2519 # Check Module style is EDK or EDKII.
2520 # Only append build option for the matched style module.
2521 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
2523 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
2526 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
2527 # if tool chain family doesn't match, skip it
2528 if Tool
in self
.ToolDefinition
and Family
!= "":
2529 FamilyIsNull
= False
2530 if self
.ToolDefinition
[Tool
].get(TAB_TOD_DEFINES_BUILDRULEFAMILY
, "") != "":
2531 if Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_BUILDRULEFAMILY
]:
2533 elif Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
2536 # expand any wildcard
2537 if Target
== "*" or Target
== self
.BuildTarget
:
2538 if Tag
== "*" or Tag
== self
.ToolChain
:
2539 if Arch
== "*" or Arch
== self
.Arch
:
2540 if Tool
not in BuildOptions
:
2541 BuildOptions
[Tool
] = {}
2542 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
] or Options
[Key
].startswith('='):
2543 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2545 # append options for the same tool except PATH
2547 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
2549 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2550 # Build Option Family has been checked, which need't to be checked again for family.
2551 if FamilyMatch
or FamilyIsNull
:
2555 if ModuleStyle
!= None and len (Key
) > 2:
2556 # Check Module style is EDK or EDKII.
2557 # Only append build option for the matched style module.
2558 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
2560 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
2563 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
2564 # if tool chain family doesn't match, skip it
2565 if Tool
not in self
.ToolDefinition
or Family
== "":
2567 # option has been added before
2568 if Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
2571 # expand any wildcard
2572 if Target
== "*" or Target
== self
.BuildTarget
:
2573 if Tag
== "*" or Tag
== self
.ToolChain
:
2574 if Arch
== "*" or Arch
== self
.Arch
:
2575 if Tool
not in BuildOptions
:
2576 BuildOptions
[Tool
] = {}
2577 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
] or Options
[Key
].startswith('='):
2578 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2580 # append options for the same tool except PATH
2582 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
2584 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2587 ## Append build options in platform to a module
2589 # @param Module The module to which the build options will be appened
2591 # @retval options The options appended with build options in platform
2593 def ApplyBuildOption(self
, Module
):
2594 # Get the different options for the different style module
2595 if Module
.AutoGenVersion
< 0x00010005:
2596 PlatformOptions
= self
.EdkBuildOption
2597 ModuleTypeOptions
= self
.Platform
.GetBuildOptionsByModuleType(EDK_NAME
, Module
.ModuleType
)
2599 PlatformOptions
= self
.EdkIIBuildOption
2600 ModuleTypeOptions
= self
.Platform
.GetBuildOptionsByModuleType(EDKII_NAME
, Module
.ModuleType
)
2601 ModuleTypeOptions
= self
._ExpandBuildOption
(ModuleTypeOptions
)
2602 ModuleOptions
= self
._ExpandBuildOption
(Module
.BuildOptions
)
2603 if Module
in self
.Platform
.Modules
:
2604 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
2605 PlatformModuleOptions
= self
._ExpandBuildOption
(PlatformModule
.BuildOptions
)
2607 PlatformModuleOptions
= {}
2609 BuildRuleOrder
= None
2610 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, ModuleTypeOptions
, PlatformModuleOptions
]:
2611 for Tool
in Options
:
2612 for Attr
in Options
[Tool
]:
2613 if Attr
== TAB_TOD_DEFINES_BUILDRULEORDER
:
2614 BuildRuleOrder
= Options
[Tool
][Attr
]
2616 AllTools
= set(ModuleOptions
.keys() + PlatformOptions
.keys() +
2617 PlatformModuleOptions
.keys() + ModuleTypeOptions
.keys() +
2618 self
.ToolDefinition
.keys())
2620 for Tool
in AllTools
:
2621 if Tool
not in BuildOptions
:
2622 BuildOptions
[Tool
] = {}
2624 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, ModuleTypeOptions
, PlatformModuleOptions
]:
2625 if Tool
not in Options
:
2627 for Attr
in Options
[Tool
]:
2628 Value
= Options
[Tool
][Attr
]
2630 # Do not generate it in Makefile
2632 if Attr
== TAB_TOD_DEFINES_BUILDRULEORDER
:
2634 if Attr
not in BuildOptions
[Tool
]:
2635 BuildOptions
[Tool
][Attr
] = ""
2636 # check if override is indicated
2637 if Value
.startswith('='):
2638 ToolPath
= Value
[1:]
2639 ToolPath
= mws
.handleWsMacro(ToolPath
)
2640 BuildOptions
[Tool
][Attr
] = ToolPath
2642 Value
= mws
.handleWsMacro(Value
)
2644 BuildOptions
[Tool
][Attr
] += " " + Value
2646 BuildOptions
[Tool
][Attr
] = Value
2647 if Module
.AutoGenVersion
< 0x00010005 and self
.Workspace
.UniFlag
!= None:
2649 # Override UNI flag only for EDK module.
2651 if 'BUILD' not in BuildOptions
:
2652 BuildOptions
['BUILD'] = {}
2653 BuildOptions
['BUILD']['FLAGS'] = self
.Workspace
.UniFlag
2654 return BuildOptions
, BuildRuleOrder
2656 Platform
= property(_GetPlatform
)
2657 Name
= property(_GetName
)
2658 Guid
= property(_GetGuid
)
2659 Version
= property(_GetVersion
)
2661 OutputDir
= property(_GetOutputDir
)
2662 BuildDir
= property(_GetBuildDir
)
2663 MakeFileDir
= property(_GetMakeFileDir
)
2664 FdfFile
= property(_GetFdfFile
)
2666 PcdTokenNumber
= property(_GetPcdTokenNumbers
) # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
2667 DynamicPcdList
= property(_GetDynamicPcdList
) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
2668 NonDynamicPcdList
= property(_GetNonDynamicPcdList
) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
2669 NonDynamicPcdDict
= property(_GetNonDynamicPcdDict
)
2670 PackageList
= property(_GetPackageList
)
2672 ToolDefinition
= property(_GetToolDefinition
) # toolcode : tool path
2673 ToolDefinitionFile
= property(_GetToolDefFile
) # toolcode : lib path
2674 ToolChainFamily
= property(_GetToolChainFamily
)
2675 BuildRuleFamily
= property(_GetBuildRuleFamily
)
2676 BuildOption
= property(_GetBuildOptions
) # toolcode : option
2677 EdkBuildOption
= property(_GetEdkBuildOptions
) # edktoolcode : option
2678 EdkIIBuildOption
= property(_GetEdkIIBuildOptions
) # edkiitoolcode : option
2680 BuildCommand
= property(_GetBuildCommand
)
2681 BuildRule
= property(_GetBuildRule
)
2682 ModuleAutoGenList
= property(_GetModuleAutoGenList
)
2683 LibraryAutoGenList
= property(_GetLibraryAutoGenList
)
2684 GenFdsCommand
= property(_GenFdsCommand
)
2686 ## ModuleAutoGen class
2688 # This class encapsules the AutoGen behaviors for the build tools. In addition to
2689 # the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according
2690 # to the [depex] section in module's inf file.
2692 class ModuleAutoGen(AutoGen
):
2693 ## Cache the timestamps of metafiles of every module in a class variable
2697 ## The real constructor of ModuleAutoGen
2699 # This method is not supposed to be called by users of ModuleAutoGen. It's
2700 # only used by factory method __new__() to do real initialization work for an
2701 # object of ModuleAutoGen
2703 # @param Workspace EdkIIWorkspaceBuild object
2704 # @param ModuleFile The path of module file
2705 # @param Target Build target (DEBUG, RELEASE)
2706 # @param Toolchain Name of tool chain
2707 # @param Arch The arch the module supports
2708 # @param PlatformFile Platform meta-file
2710 def _Init(self
, Workspace
, ModuleFile
, Target
, Toolchain
, Arch
, PlatformFile
):
2711 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen module [%s] [%s]" % (ModuleFile
, Arch
))
2712 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (ModuleFile
, Arch
, Toolchain
, Target
)
2714 self
.Workspace
= Workspace
2715 self
.WorkspaceDir
= Workspace
.WorkspaceDir
2717 self
.MetaFile
= ModuleFile
2718 self
.PlatformInfo
= PlatformAutoGen(Workspace
, PlatformFile
, Target
, Toolchain
, Arch
)
2719 # check if this module is employed by active platform
2720 if not self
.PlatformInfo
.ValidModule(self
.MetaFile
):
2721 EdkLogger
.verbose("Module [%s] for [%s] is not employed by active platform\n" \
2722 % (self
.MetaFile
, Arch
))
2725 self
.SourceDir
= self
.MetaFile
.SubDir
2726 self
.SourceDir
= mws
.relpath(self
.SourceDir
, self
.WorkspaceDir
)
2728 self
.SourceOverrideDir
= None
2729 # use overrided path defined in DSC file
2730 if self
.MetaFile
.Key
in GlobalData
.gOverrideDir
:
2731 self
.SourceOverrideDir
= GlobalData
.gOverrideDir
[self
.MetaFile
.Key
]
2733 self
.ToolChain
= Toolchain
2734 self
.BuildTarget
= Target
2736 self
.ToolChainFamily
= self
.PlatformInfo
.ToolChainFamily
2737 self
.BuildRuleFamily
= self
.PlatformInfo
.BuildRuleFamily
2739 self
.IsMakeFileCreated
= False
2740 self
.IsCodeFileCreated
= False
2741 self
.IsAsBuiltInfCreated
= False
2742 self
.DepexGenerated
= False
2744 self
.BuildDatabase
= self
.Workspace
.BuildDatabase
2745 self
.BuildRuleOrder
= None
2751 self
._Version
= None
2752 self
._ModuleType
= None
2753 self
._ComponentType
= None
2754 self
._PcdIsDriver
= None
2755 self
._AutoGenVersion
= None
2756 self
._LibraryFlag
= None
2757 self
._CustomMakefile
= None
2760 self
._BuildDir
= None
2761 self
._OutputDir
= None
2762 self
._DebugDir
= None
2763 self
._MakeFileDir
= None
2765 self
._IncludePathList
= None
2766 self
._IncludePathLength
= 0
2767 self
._AutoGenFileList
= None
2768 self
._UnicodeFileList
= None
2769 self
._VfrFileList
= None
2770 self
._IdfFileList
= None
2771 self
._SourceFileList
= None
2772 self
._ObjectFileList
= None
2773 self
._BinaryFileList
= None
2775 self
._DependentPackageList
= None
2776 self
._DependentLibraryList
= None
2777 self
._LibraryAutoGenList
= None
2778 self
._DerivedPackageList
= None
2779 self
._ModulePcdList
= None
2780 self
._LibraryPcdList
= None
2781 self
._PcdComments
= sdict()
2782 self
._GuidList
= None
2783 self
._GuidsUsedByPcd
= None
2784 self
._GuidComments
= sdict()
2785 self
._ProtocolList
= None
2786 self
._ProtocolComments
= sdict()
2787 self
._PpiList
= None
2788 self
._PpiComments
= sdict()
2789 self
._DepexList
= None
2790 self
._DepexExpressionList
= None
2791 self
._BuildOption
= None
2792 self
._BuildOptionIncPathList
= None
2793 self
._BuildTargets
= None
2794 self
._IntroBuildTargetList
= None
2795 self
._FinalBuildTargetList
= None
2796 self
._FileTypes
= None
2797 self
._BuildRules
= None
2799 self
._TimeStampPath
= None
2801 self
.AutoGenDepSet
= set()
2804 ## The Modules referenced to this Library
2805 # Only Library has this attribute
2806 self
._ReferenceModules
= []
2808 ## Store the FixedAtBuild Pcds
2810 self
._FixedAtBuildPcds
= []
2815 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
2817 # Get FixedAtBuild Pcds of this Module
2818 def _GetFixedAtBuildPcds(self
):
2819 if self
._FixedAtBuildPcds
:
2820 return self
._FixedAtBuildPcds
2821 for Pcd
in self
.ModulePcdList
:
2822 if Pcd
.Type
!= "FixedAtBuild":
2824 if Pcd
not in self
._FixedAtBuildPcds
:
2825 self
._FixedAtBuildPcds
.append(Pcd
)
2827 return self
._FixedAtBuildPcds
2829 def _GetUniqueBaseName(self
):
2830 BaseName
= self
.Name
2831 for Module
in self
.PlatformInfo
.ModuleAutoGenList
:
2832 if Module
.MetaFile
== self
.MetaFile
:
2834 if Module
.Name
== self
.Name
:
2835 if uuid
.UUID(Module
.Guid
) == uuid
.UUID(self
.Guid
):
2836 EdkLogger
.error("build", FILE_DUPLICATED
, 'Modules have same BaseName and FILE_GUID:\n'
2837 ' %s\n %s' % (Module
.MetaFile
, self
.MetaFile
))
2838 BaseName
= '%s_%s' % (self
.Name
, self
.Guid
)
2841 # Macros could be used in build_rule.txt (also Makefile)
2842 def _GetMacros(self
):
2843 if self
._Macro
== None:
2844 self
._Macro
= sdict()
2845 self
._Macro
["WORKSPACE" ] = self
.WorkspaceDir
2846 self
._Macro
["MODULE_NAME" ] = self
.Name
2847 self
._Macro
["MODULE_NAME_GUID" ] = self
._GetUniqueBaseName
()
2848 self
._Macro
["MODULE_GUID" ] = self
.Guid
2849 self
._Macro
["MODULE_VERSION" ] = self
.Version
2850 self
._Macro
["MODULE_TYPE" ] = self
.ModuleType
2851 self
._Macro
["MODULE_FILE" ] = str(self
.MetaFile
)
2852 self
._Macro
["MODULE_FILE_BASE_NAME" ] = self
.MetaFile
.BaseName
2853 self
._Macro
["MODULE_RELATIVE_DIR" ] = self
.SourceDir
2854 self
._Macro
["MODULE_DIR" ] = self
.SourceDir
2856 self
._Macro
["BASE_NAME" ] = self
.Name
2858 self
._Macro
["ARCH" ] = self
.Arch
2859 self
._Macro
["TOOLCHAIN" ] = self
.ToolChain
2860 self
._Macro
["TOOLCHAIN_TAG" ] = self
.ToolChain
2861 self
._Macro
["TOOL_CHAIN_TAG" ] = self
.ToolChain
2862 self
._Macro
["TARGET" ] = self
.BuildTarget
2864 self
._Macro
["BUILD_DIR" ] = self
.PlatformInfo
.BuildDir
2865 self
._Macro
["BIN_DIR" ] = os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)
2866 self
._Macro
["LIB_DIR" ] = os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)
2867 self
._Macro
["MODULE_BUILD_DIR" ] = self
.BuildDir
2868 self
._Macro
["OUTPUT_DIR" ] = self
.OutputDir
2869 self
._Macro
["DEBUG_DIR" ] = self
.DebugDir
2870 self
._Macro
["DEST_DIR_OUTPUT" ] = self
.OutputDir
2871 self
._Macro
["DEST_DIR_DEBUG" ] = self
.DebugDir
2872 self
._Macro
["PLATFORM_NAME" ] = self
.PlatformInfo
.Name
2873 self
._Macro
["PLATFORM_GUID" ] = self
.PlatformInfo
.Guid
2874 self
._Macro
["PLATFORM_VERSION" ] = self
.PlatformInfo
.Version
2875 self
._Macro
["PLATFORM_RELATIVE_DIR" ] = self
.PlatformInfo
.SourceDir
2876 self
._Macro
["PLATFORM_DIR" ] = mws
.join(self
.WorkspaceDir
, self
.PlatformInfo
.SourceDir
)
2877 self
._Macro
["PLATFORM_OUTPUT_DIR" ] = self
.PlatformInfo
.OutputDir
2880 ## Return the module build data object
2881 def _GetModule(self
):
2882 if self
._Module
== None:
2883 self
._Module
= self
.Workspace
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
2886 ## Return the module name
2887 def _GetBaseName(self
):
2888 return self
.Module
.BaseName
2890 ## Return the module DxsFile if exist
2891 def _GetDxsFile(self
):
2892 return self
.Module
.DxsFile
2894 ## Return the module SourceOverridePath
2895 def _GetSourceOverridePath(self
):
2896 return self
.Module
.SourceOverridePath
2898 ## Return the module meta-file GUID
2901 # To build same module more than once, the module path with FILE_GUID overridden has
2902 # the file name FILE_GUIDmodule.inf, but the relative path (self.MetaFile.File) is the realy path
2903 # in DSC. The overridden GUID can be retrieved from file name
2905 if os
.path
.basename(self
.MetaFile
.File
) != os
.path
.basename(self
.MetaFile
.Path
):
2907 # Length of GUID is 36
2909 return os
.path
.basename(self
.MetaFile
.Path
)[:36]
2910 return self
.Module
.Guid
2912 ## Return the module version
2913 def _GetVersion(self
):
2914 return self
.Module
.Version
2916 ## Return the module type
2917 def _GetModuleType(self
):
2918 return self
.Module
.ModuleType
2920 ## Return the component type (for Edk.x style of module)
2921 def _GetComponentType(self
):
2922 return self
.Module
.ComponentType
2924 ## Return the build type
2925 def _GetBuildType(self
):
2926 return self
.Module
.BuildType
2928 ## Return the PCD_IS_DRIVER setting
2929 def _GetPcdIsDriver(self
):
2930 return self
.Module
.PcdIsDriver
2932 ## Return the autogen version, i.e. module meta-file version
2933 def _GetAutoGenVersion(self
):
2934 return self
.Module
.AutoGenVersion
2936 ## Check if the module is library or not
2937 def _IsLibrary(self
):
2938 if self
._LibraryFlag
== None:
2939 if self
.Module
.LibraryClass
!= None and self
.Module
.LibraryClass
!= []:
2940 self
._LibraryFlag
= True
2942 self
._LibraryFlag
= False
2943 return self
._LibraryFlag
2945 ## Check if the module is binary module or not
2946 def _IsBinaryModule(self
):
2947 return self
.Module
.IsBinaryModule
2949 ## Return the directory to store intermediate files of the module
2950 def _GetBuildDir(self
):
2951 if self
._BuildDir
== None:
2952 self
._BuildDir
= path
.join(
2953 self
.PlatformInfo
.BuildDir
,
2956 self
.MetaFile
.BaseName
2958 CreateDirectory(self
._BuildDir
)
2959 return self
._BuildDir
2961 ## Return the directory to store the intermediate object files of the mdoule
2962 def _GetOutputDir(self
):
2963 if self
._OutputDir
== None:
2964 self
._OutputDir
= path
.join(self
.BuildDir
, "OUTPUT")
2965 CreateDirectory(self
._OutputDir
)
2966 return self
._OutputDir
2968 ## Return the directory to store auto-gened source files of the mdoule
2969 def _GetDebugDir(self
):
2970 if self
._DebugDir
== None:
2971 self
._DebugDir
= path
.join(self
.BuildDir
, "DEBUG")
2972 CreateDirectory(self
._DebugDir
)
2973 return self
._DebugDir
2975 ## Return the path of custom file
2976 def _GetCustomMakefile(self
):
2977 if self
._CustomMakefile
== None:
2978 self
._CustomMakefile
= {}
2979 for Type
in self
.Module
.CustomMakefile
:
2980 if Type
in gMakeTypeMap
:
2981 MakeType
= gMakeTypeMap
[Type
]
2984 if self
.SourceOverrideDir
!= None:
2985 File
= os
.path
.join(self
.SourceOverrideDir
, self
.Module
.CustomMakefile
[Type
])
2986 if not os
.path
.exists(File
):
2987 File
= os
.path
.join(self
.SourceDir
, self
.Module
.CustomMakefile
[Type
])
2989 File
= os
.path
.join(self
.SourceDir
, self
.Module
.CustomMakefile
[Type
])
2990 self
._CustomMakefile
[MakeType
] = File
2991 return self
._CustomMakefile
2993 ## Return the directory of the makefile
2995 # @retval string The directory string of module's makefile
2997 def _GetMakeFileDir(self
):
2998 return self
.BuildDir
3000 ## Return build command string
3002 # @retval string Build command string
3004 def _GetBuildCommand(self
):
3005 return self
.PlatformInfo
.BuildCommand
3007 ## Get object list of all packages the module and its dependent libraries belong to
3009 # @retval list The list of package object
3011 def _GetDerivedPackageList(self
):
3013 for M
in [self
.Module
] + self
.DependentLibraryList
:
3014 for Package
in M
.Packages
:
3015 if Package
in PackageList
:
3017 PackageList
.append(Package
)
3020 ## Get the depex string
3022 # @return : a string contain all depex expresion.
3023 def _GetDepexExpresionString(self
):
3026 ## DPX_SOURCE IN Define section.
3027 if self
.Module
.DxsFile
:
3029 for M
in [self
.Module
] + self
.DependentLibraryList
:
3030 Filename
= M
.MetaFile
.Path
3031 InfObj
= InfSectionParser
.InfSectionParser(Filename
)
3032 DepexExpresionList
= InfObj
.GetDepexExpresionList()
3033 for DepexExpresion
in DepexExpresionList
:
3034 for key
in DepexExpresion
.keys():
3035 Arch
, ModuleType
= key
3036 DepexExpr
= [x
for x
in DepexExpresion
[key
] if not str(x
).startswith('#')]
3037 # the type of build module is USER_DEFINED.
3038 # All different DEPEX section tags would be copied into the As Built INF file
3039 # and there would be separate DEPEX section tags
3040 if self
.ModuleType
.upper() == SUP_MODULE_USER_DEFINED
:
3041 if (Arch
.upper() == self
.Arch
.upper()) and (ModuleType
.upper() != TAB_ARCH_COMMON
):
3042 DepexList
.append({(Arch
, ModuleType
): DepexExpr
})
3044 if Arch
.upper() == TAB_ARCH_COMMON
or \
3045 (Arch
.upper() == self
.Arch
.upper() and \
3046 ModuleType
.upper() in [TAB_ARCH_COMMON
, self
.ModuleType
.upper()]):
3047 DepexList
.append({(Arch
, ModuleType
): DepexExpr
})
3049 #the type of build module is USER_DEFINED.
3050 if self
.ModuleType
.upper() == SUP_MODULE_USER_DEFINED
:
3051 for Depex
in DepexList
:
3052 for key
in Depex
.keys():
3053 DepexStr
+= '[Depex.%s.%s]\n' % key
3054 DepexStr
+= '\n'.join(['# '+ val
for val
in Depex
[key
]])
3057 return '[Depex.%s]\n' % self
.Arch
3060 #the type of build module not is USER_DEFINED.
3062 for Depex
in DepexList
:
3067 for D
in Depex
.values():
3068 DepexStr
+= ' '.join([val
for val
in D
])
3069 Index
= DepexStr
.find('END')
3070 if Index
> -1 and Index
== len(DepexStr
) - 3:
3071 DepexStr
= DepexStr
[:-3]
3072 DepexStr
= DepexStr
.strip()
3075 DepexStr
= DepexStr
.lstrip('(').rstrip(')').strip()
3077 return '[Depex.%s]\n' % self
.Arch
3078 return '[Depex.%s]\n# ' % self
.Arch
+ DepexStr
3080 ## Merge dependency expression
3082 # @retval list The token list of the dependency expression after parsed
3084 def _GetDepexTokenList(self
):
3085 if self
._DepexList
== None:
3086 self
._DepexList
= {}
3087 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
3088 return self
._DepexList
3090 self
._DepexList
[self
.ModuleType
] = []
3092 for ModuleType
in self
._DepexList
:
3093 DepexList
= self
._DepexList
[ModuleType
]
3095 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
3097 for M
in [self
.Module
] + self
.DependentLibraryList
:
3099 for D
in M
.Depex
[self
.Arch
, ModuleType
]:
3101 DepexList
.append('AND')
3102 DepexList
.append('(')
3104 if DepexList
[-1] == 'END': # no need of a END at this time
3106 DepexList
.append(')')
3109 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexList
))
3110 if 'BEFORE' in DepexList
or 'AFTER' in DepexList
:
3112 if len(DepexList
) > 0:
3113 EdkLogger
.verbose('')
3114 return self
._DepexList
3116 ## Merge dependency expression
3118 # @retval list The token list of the dependency expression after parsed
3120 def _GetDepexExpressionTokenList(self
):
3121 if self
._DepexExpressionList
== None:
3122 self
._DepexExpressionList
= {}
3123 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
3124 return self
._DepexExpressionList
3126 self
._DepexExpressionList
[self
.ModuleType
] = ''
3128 for ModuleType
in self
._DepexExpressionList
:
3129 DepexExpressionList
= self
._DepexExpressionList
[ModuleType
]
3131 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
3133 for M
in [self
.Module
] + self
.DependentLibraryList
:
3135 for D
in M
.DepexExpression
[self
.Arch
, ModuleType
]:
3136 if DepexExpressionList
!= '':
3137 DepexExpressionList
+= ' AND '
3138 DepexExpressionList
+= '('
3139 DepexExpressionList
+= D
3140 DepexExpressionList
= DepexExpressionList
.rstrip('END').strip()
3141 DepexExpressionList
+= ')'
3144 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexExpressionList
))
3145 if 'BEFORE' in DepexExpressionList
or 'AFTER' in DepexExpressionList
:
3147 if len(DepexExpressionList
) > 0:
3148 EdkLogger
.verbose('')
3149 self
._DepexExpressionList
[ModuleType
] = DepexExpressionList
3150 return self
._DepexExpressionList
3152 # Get the tiano core user extension, it is contain dependent library.
3153 # @retval: a list contain tiano core userextension.
3155 def _GetTianoCoreUserExtensionList(self
):
3156 TianoCoreUserExtentionList
= []
3157 for M
in [self
.Module
] + self
.DependentLibraryList
:
3158 Filename
= M
.MetaFile
.Path
3159 InfObj
= InfSectionParser
.InfSectionParser(Filename
)
3160 TianoCoreUserExtenList
= InfObj
.GetUserExtensionTianoCore()
3161 for TianoCoreUserExtent
in TianoCoreUserExtenList
:
3162 for Section
in TianoCoreUserExtent
.keys():
3163 ItemList
= Section
.split(TAB_SPLIT
)
3165 if len(ItemList
) == 4:
3167 if Arch
.upper() == TAB_ARCH_COMMON
or Arch
.upper() == self
.Arch
.upper():
3169 TianoCoreList
.extend([TAB_SECTION_START
+ Section
+ TAB_SECTION_END
])
3170 TianoCoreList
.extend(TianoCoreUserExtent
[Section
][:])
3171 TianoCoreList
.append('\n')
3172 TianoCoreUserExtentionList
.append(TianoCoreList
)
3174 return TianoCoreUserExtentionList
3176 ## Return the list of specification version required for the module
3178 # @retval list The list of specification defined in module file
3180 def _GetSpecification(self
):
3181 return self
.Module
.Specification
3183 ## Tool option for the module build
3185 # @param PlatformInfo The object of PlatformBuildInfo
3186 # @retval dict The dict containing valid options
3188 def _GetModuleBuildOption(self
):
3189 if self
._BuildOption
== None:
3190 self
._BuildOption
, self
.BuildRuleOrder
= self
.PlatformInfo
.ApplyBuildOption(self
.Module
)
3191 if self
.BuildRuleOrder
:
3192 self
.BuildRuleOrder
= ['.%s' % Ext
for Ext
in self
.BuildRuleOrder
.split()]
3193 return self
._BuildOption
3195 ## Get include path list from tool option for the module build
3197 # @retval list The include path list
3199 def _GetBuildOptionIncPathList(self
):
3200 if self
._BuildOptionIncPathList
== None:
3202 # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
3203 # is the former use /I , the Latter used -I to specify include directories
3205 if self
.PlatformInfo
.ToolChainFamily
in ('MSFT'):
3206 gBuildOptIncludePattern
= re
.compile(r
"(?:.*?)/I[ \t]*([^ ]*)", re
.MULTILINE | re
.DOTALL
)
3207 elif self
.PlatformInfo
.ToolChainFamily
in ('INTEL', 'GCC', 'RVCT'):
3208 gBuildOptIncludePattern
= re
.compile(r
"(?:.*?)-I[ \t]*([^ ]*)", re
.MULTILINE | re
.DOTALL
)
3211 # New ToolChainFamily, don't known whether there is option to specify include directories
3213 self
._BuildOptionIncPathList
= []
3214 return self
._BuildOptionIncPathList
3216 BuildOptionIncPathList
= []
3217 for Tool
in ('CC', 'PP', 'VFRPP', 'ASLPP', 'ASLCC', 'APP', 'ASM'):
3220 FlagOption
= self
.BuildOption
[Tool
][Attr
]
3224 if self
.PlatformInfo
.ToolChainFamily
!= 'RVCT':
3225 IncPathList
= [NormPath(Path
, self
.Macros
) for Path
in gBuildOptIncludePattern
.findall(FlagOption
)]
3228 # RVCT may specify a list of directory seperated by commas
3231 for Path
in gBuildOptIncludePattern
.findall(FlagOption
):
3232 PathList
= GetSplitList(Path
, TAB_COMMA_SPLIT
)
3233 IncPathList
+= [NormPath(PathEntry
, self
.Macros
) for PathEntry
in PathList
]
3236 # EDK II modules must not reference header files outside of the packages they depend on or
3237 # within the module's directory tree. Report error if violation.
3239 if self
.AutoGenVersion
>= 0x00010005 and len(IncPathList
) > 0:
3240 for Path
in IncPathList
:
3241 if (Path
not in self
.IncludePathList
) and (CommonPath([Path
, self
.MetaFile
.Dir
]) != self
.MetaFile
.Dir
):
3242 ErrMsg
= "The include directory for the EDK II module in this line is invalid %s specified in %s FLAGS '%s'" % (Path
, Tool
, FlagOption
)
3243 EdkLogger
.error("build",
3246 File
=str(self
.MetaFile
))
3249 BuildOptionIncPathList
+= IncPathList
3251 self
._BuildOptionIncPathList
= BuildOptionIncPathList
3253 return self
._BuildOptionIncPathList
3255 ## Return a list of files which can be built from source
3257 # What kind of files can be built is determined by build rules in
3258 # $(CONF_DIRECTORY)/build_rule.txt and toolchain family.
3260 def _GetSourceFileList(self
):
3261 if self
._SourceFileList
== None:
3262 self
._SourceFileList
= []
3263 for F
in self
.Module
.Sources
:
3265 if F
.TagName
not in ("", "*", self
.ToolChain
):
3266 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "The toolchain [%s] for processing file [%s] is found, "
3267 "but [%s] is needed" % (F
.TagName
, str(F
), self
.ToolChain
))
3269 # match tool chain family
3270 if F
.ToolChainFamily
not in ("", "*", self
.ToolChainFamily
):
3273 "The file [%s] must be built by tools of [%s], " \
3274 "but current toolchain family is [%s]" \
3275 % (str(F
), F
.ToolChainFamily
, self
.ToolChainFamily
))
3278 # add the file path into search path list for file including
3279 if F
.Dir
not in self
.IncludePathList
and self
.AutoGenVersion
>= 0x00010005:
3280 self
.IncludePathList
.insert(0, F
.Dir
)
3281 self
._SourceFileList
.append(F
)
3283 self
._MatchBuildRuleOrder
(self
._SourceFileList
)
3285 for F
in self
._SourceFileList
:
3286 self
._ApplyBuildRule
(F
, TAB_UNKNOWN_FILE
)
3287 return self
._SourceFileList
3289 def _MatchBuildRuleOrder(self
, FileList
):
3291 self
._GetModuleBuildOption
()
3292 for SingleFile
in FileList
:
3293 if self
.BuildRuleOrder
and SingleFile
.Ext
in self
.BuildRuleOrder
and SingleFile
.Ext
in self
.BuildRules
:
3294 key
= SingleFile
.Path
.split(SingleFile
.Ext
)[0]
3295 if key
in Order_Dict
:
3296 Order_Dict
[key
].append(SingleFile
.Ext
)
3298 Order_Dict
[key
] = [SingleFile
.Ext
]
3301 for F
in Order_Dict
:
3302 if len(Order_Dict
[F
]) > 1:
3303 Order_Dict
[F
].sort(key
=lambda i
: self
.BuildRuleOrder
.index(i
))
3304 for Ext
in Order_Dict
[F
][1:]:
3305 RemoveList
.append(F
+ Ext
)
3307 for item
in RemoveList
:
3308 FileList
.remove(item
)
3312 ## Return the list of unicode files
3313 def _GetUnicodeFileList(self
):
3314 if self
._UnicodeFileList
== None:
3315 if TAB_UNICODE_FILE
in self
.FileTypes
:
3316 self
._UnicodeFileList
= self
.FileTypes
[TAB_UNICODE_FILE
]
3318 self
._UnicodeFileList
= []
3319 return self
._UnicodeFileList
3321 ## Return the list of vfr files
3322 def _GetVfrFileList(self
):
3323 if self
._VfrFileList
== None:
3324 if TAB_VFR_FILE
in self
.FileTypes
:
3325 self
._VfrFileList
= self
.FileTypes
[TAB_VFR_FILE
]
3327 self
._VfrFileList
= []
3328 return self
._VfrFileList
3330 ## Return the list of Image Definition files
3331 def _GetIdfFileList(self
):
3332 if self
._IdfFileList
== None:
3333 if TAB_IMAGE_FILE
in self
.FileTypes
:
3334 self
._IdfFileList
= self
.FileTypes
[TAB_IMAGE_FILE
]
3336 self
._IdfFileList
= []
3337 return self
._IdfFileList
3339 ## Return a list of files which can be built from binary
3341 # "Build" binary files are just to copy them to build directory.
3343 # @retval list The list of files which can be built later
3345 def _GetBinaryFiles(self
):
3346 if self
._BinaryFileList
== None:
3347 self
._BinaryFileList
= []
3348 for F
in self
.Module
.Binaries
:
3349 if F
.Target
not in ['COMMON', '*'] and F
.Target
!= self
.BuildTarget
:
3351 self
._BinaryFileList
.append(F
)
3352 self
._ApplyBuildRule
(F
, F
.Type
)
3353 return self
._BinaryFileList
3355 def _GetBuildRules(self
):
3356 if self
._BuildRules
== None:
3358 BuildRuleDatabase
= self
.PlatformInfo
.BuildRule
3359 for Type
in BuildRuleDatabase
.FileTypeList
:
3360 #first try getting build rule by BuildRuleFamily
3361 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.BuildRuleFamily
]
3363 # build type is always module type, but ...
3364 if self
.ModuleType
!= self
.BuildType
:
3365 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.BuildRuleFamily
]
3366 #second try getting build rule by ToolChainFamily
3368 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.ToolChainFamily
]
3370 # build type is always module type, but ...
3371 if self
.ModuleType
!= self
.BuildType
:
3372 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.ToolChainFamily
]
3375 RuleObject
= RuleObject
.Instantiate(self
.Macros
)
3376 BuildRules
[Type
] = RuleObject
3377 for Ext
in RuleObject
.SourceFileExtList
:
3378 BuildRules
[Ext
] = RuleObject
3379 self
._BuildRules
= BuildRules
3380 return self
._BuildRules
3382 def _ApplyBuildRule(self
, File
, FileType
):
3383 if self
._BuildTargets
== None:
3384 self
._IntroBuildTargetList
= set()
3385 self
._FinalBuildTargetList
= set()
3386 self
._BuildTargets
= {}
3387 self
._FileTypes
= {}
3389 SubDirectory
= os
.path
.join(self
.OutputDir
, File
.SubDir
)
3390 if not os
.path
.exists(SubDirectory
):
3391 CreateDirectory(SubDirectory
)
3397 # Make sure to get build rule order value
3399 self
._GetModuleBuildOption
()
3401 while Index
< len(SourceList
):
3402 Source
= SourceList
[Index
]
3406 CreateDirectory(Source
.Dir
)
3408 if File
.IsBinary
and File
== Source
and self
._BinaryFileList
!= None and File
in self
._BinaryFileList
:
3409 # Skip all files that are not binary libraries
3410 if not self
.IsLibrary
:
3412 RuleObject
= self
.BuildRules
[TAB_DEFAULT_BINARY_FILE
]
3413 elif FileType
in self
.BuildRules
:
3414 RuleObject
= self
.BuildRules
[FileType
]
3415 elif Source
.Ext
in self
.BuildRules
:
3416 RuleObject
= self
.BuildRules
[Source
.Ext
]
3418 # stop at no more rules
3420 self
._FinalBuildTargetList
.add(LastTarget
)
3423 FileType
= RuleObject
.SourceFileType
3424 if FileType
not in self
._FileTypes
:
3425 self
._FileTypes
[FileType
] = set()
3426 self
._FileTypes
[FileType
].add(Source
)
3428 # stop at STATIC_LIBRARY for library
3429 if self
.IsLibrary
and FileType
== TAB_STATIC_LIBRARY
:
3431 self
._FinalBuildTargetList
.add(LastTarget
)
3434 Target
= RuleObject
.Apply(Source
, self
.BuildRuleOrder
)
3437 self
._FinalBuildTargetList
.add(LastTarget
)
3439 elif not Target
.Outputs
:
3440 # Only do build for target with outputs
3441 self
._FinalBuildTargetList
.add(Target
)
3443 if FileType
not in self
._BuildTargets
:
3444 self
._BuildTargets
[FileType
] = set()
3445 self
._BuildTargets
[FileType
].add(Target
)
3447 if not Source
.IsBinary
and Source
== File
:
3448 self
._IntroBuildTargetList
.add(Target
)
3450 # to avoid cyclic rule
3451 if FileType
in RuleChain
:
3454 RuleChain
.append(FileType
)
3455 SourceList
.extend(Target
.Outputs
)
3457 FileType
= TAB_UNKNOWN_FILE
3459 def _GetTargets(self
):
3460 if self
._BuildTargets
== None:
3461 self
._IntroBuildTargetList
= set()
3462 self
._FinalBuildTargetList
= set()
3463 self
._BuildTargets
= {}
3464 self
._FileTypes
= {}
3466 #TRICK: call _GetSourceFileList to apply build rule for source files
3467 if self
.SourceFileList
:
3470 #TRICK: call _GetBinaryFileList to apply build rule for binary files
3471 if self
.BinaryFileList
:
3474 return self
._BuildTargets
3476 def _GetIntroTargetList(self
):
3478 return self
._IntroBuildTargetList
3480 def _GetFinalTargetList(self
):
3482 return self
._FinalBuildTargetList
3484 def _GetFileTypes(self
):
3486 return self
._FileTypes
3488 ## Get the list of package object the module depends on
3490 # @retval list The package object list
3492 def _GetDependentPackageList(self
):
3493 return self
.Module
.Packages
3495 ## Return the list of auto-generated code file
3497 # @retval list The list of auto-generated file
3499 def _GetAutoGenFileList(self
):
3500 UniStringAutoGenC
= True
3501 IdfStringAutoGenC
= True
3502 UniStringBinBuffer
= StringIO()
3503 IdfGenBinBuffer
= StringIO()
3504 if self
.BuildType
== 'UEFI_HII':
3505 UniStringAutoGenC
= False
3506 IdfStringAutoGenC
= False
3507 if self
._AutoGenFileList
== None:
3508 self
._AutoGenFileList
= {}
3509 AutoGenC
= TemplateString()
3510 AutoGenH
= TemplateString()
3511 StringH
= TemplateString()
3512 StringIdf
= TemplateString()
3513 GenC
.CreateCode(self
, AutoGenC
, AutoGenH
, StringH
, UniStringAutoGenC
, UniStringBinBuffer
, StringIdf
, IdfStringAutoGenC
, IdfGenBinBuffer
)
3515 # AutoGen.c is generated if there are library classes in inf, or there are object files
3517 if str(AutoGenC
) != "" and (len(self
.Module
.LibraryClasses
) > 0
3518 or TAB_OBJECT_FILE
in self
.FileTypes
):
3519 AutoFile
= PathClass(gAutoGenCodeFileName
, self
.DebugDir
)
3520 self
._AutoGenFileList
[AutoFile
] = str(AutoGenC
)
3521 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3522 if str(AutoGenH
) != "":
3523 AutoFile
= PathClass(gAutoGenHeaderFileName
, self
.DebugDir
)
3524 self
._AutoGenFileList
[AutoFile
] = str(AutoGenH
)
3525 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3526 if str(StringH
) != "":
3527 AutoFile
= PathClass(gAutoGenStringFileName
% {"module_name":self
.Name
}, self
.DebugDir
)
3528 self
._AutoGenFileList
[AutoFile
] = str(StringH
)
3529 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3530 if UniStringBinBuffer
!= None and UniStringBinBuffer
.getvalue() != "":
3531 AutoFile
= PathClass(gAutoGenStringFormFileName
% {"module_name":self
.Name
}, self
.OutputDir
)
3532 self
._AutoGenFileList
[AutoFile
] = UniStringBinBuffer
.getvalue()
3533 AutoFile
.IsBinary
= True
3534 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3535 if UniStringBinBuffer
!= None:
3536 UniStringBinBuffer
.close()
3537 if str(StringIdf
) != "":
3538 AutoFile
= PathClass(gAutoGenImageDefFileName
% {"module_name":self
.Name
}, self
.DebugDir
)
3539 self
._AutoGenFileList
[AutoFile
] = str(StringIdf
)
3540 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3541 if IdfGenBinBuffer
!= None and IdfGenBinBuffer
.getvalue() != "":
3542 AutoFile
= PathClass(gAutoGenIdfFileName
% {"module_name":self
.Name
}, self
.OutputDir
)
3543 self
._AutoGenFileList
[AutoFile
] = IdfGenBinBuffer
.getvalue()
3544 AutoFile
.IsBinary
= True
3545 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3546 if IdfGenBinBuffer
!= None:
3547 IdfGenBinBuffer
.close()
3548 return self
._AutoGenFileList
3550 ## Return the list of library modules explicitly or implicityly used by this module
3551 def _GetLibraryList(self
):
3552 if self
._DependentLibraryList
== None:
3553 # only merge library classes and PCD for non-library module
3555 self
._DependentLibraryList
= []
3557 if self
.AutoGenVersion
< 0x00010005:
3558 self
._DependentLibraryList
= self
.PlatformInfo
.ResolveLibraryReference(self
.Module
)
3560 self
._DependentLibraryList
= self
.PlatformInfo
.ApplyLibraryInstance(self
.Module
)
3561 return self
._DependentLibraryList
3564 def UpdateComments(Recver
, Src
):
3566 if Key
not in Recver
:
3568 Recver
[Key
].extend(Src
[Key
])
3569 ## Get the list of PCDs from current module
3571 # @retval list The list of PCD
3573 def _GetModulePcdList(self
):
3574 if self
._ModulePcdList
== None:
3575 # apply PCD settings from platform
3576 self
._ModulePcdList
= self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, self
.Module
.Pcds
)
3577 self
.UpdateComments(self
._PcdComments
, self
.Module
.PcdComments
)
3578 return self
._ModulePcdList
3580 ## Get the list of PCDs from dependent libraries
3582 # @retval list The list of PCD
3584 def _GetLibraryPcdList(self
):
3585 if self
._LibraryPcdList
== None:
3587 if not self
.IsLibrary
:
3588 # get PCDs from dependent libraries
3589 for Library
in self
.DependentLibraryList
:
3590 self
.UpdateComments(self
._PcdComments
, Library
.PcdComments
)
3591 for Key
in Library
.Pcds
:
3592 # skip duplicated PCDs
3593 if Key
in self
.Module
.Pcds
or Key
in Pcds
:
3595 Pcds
[Key
] = copy
.copy(Library
.Pcds
[Key
])
3596 # apply PCD settings from platform
3597 self
._LibraryPcdList
= self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, Pcds
)
3599 self
._LibraryPcdList
= []
3600 return self
._LibraryPcdList
3602 ## Get the GUID value mapping
3604 # @retval dict The mapping between GUID cname and its value
3606 def _GetGuidList(self
):
3607 if self
._GuidList
== None:
3608 self
._GuidList
= sdict()
3609 self
._GuidList
.update(self
.Module
.Guids
)
3610 for Library
in self
.DependentLibraryList
:
3611 self
._GuidList
.update(Library
.Guids
)
3612 self
.UpdateComments(self
._GuidComments
, Library
.GuidComments
)
3613 self
.UpdateComments(self
._GuidComments
, self
.Module
.GuidComments
)
3614 return self
._GuidList
3616 def GetGuidsUsedByPcd(self
):
3617 if self
._GuidsUsedByPcd
== None:
3618 self
._GuidsUsedByPcd
= sdict()
3619 self
._GuidsUsedByPcd
.update(self
.Module
.GetGuidsUsedByPcd())
3620 for Library
in self
.DependentLibraryList
:
3621 self
._GuidsUsedByPcd
.update(Library
.GetGuidsUsedByPcd())
3622 return self
._GuidsUsedByPcd
3623 ## Get the protocol value mapping
3625 # @retval dict The mapping between protocol cname and its value
3627 def _GetProtocolList(self
):
3628 if self
._ProtocolList
== None:
3629 self
._ProtocolList
= sdict()
3630 self
._ProtocolList
.update(self
.Module
.Protocols
)
3631 for Library
in self
.DependentLibraryList
:
3632 self
._ProtocolList
.update(Library
.Protocols
)
3633 self
.UpdateComments(self
._ProtocolComments
, Library
.ProtocolComments
)
3634 self
.UpdateComments(self
._ProtocolComments
, self
.Module
.ProtocolComments
)
3635 return self
._ProtocolList
3637 ## Get the PPI value mapping
3639 # @retval dict The mapping between PPI cname and its value
3641 def _GetPpiList(self
):
3642 if self
._PpiList
== None:
3643 self
._PpiList
= sdict()
3644 self
._PpiList
.update(self
.Module
.Ppis
)
3645 for Library
in self
.DependentLibraryList
:
3646 self
._PpiList
.update(Library
.Ppis
)
3647 self
.UpdateComments(self
._PpiComments
, Library
.PpiComments
)
3648 self
.UpdateComments(self
._PpiComments
, self
.Module
.PpiComments
)
3649 return self
._PpiList
3651 ## Get the list of include search path
3653 # @retval list The list path
3655 def _GetIncludePathList(self
):
3656 if self
._IncludePathList
== None:
3657 self
._IncludePathList
= []
3658 if self
.AutoGenVersion
< 0x00010005:
3659 for Inc
in self
.Module
.Includes
:
3660 if Inc
not in self
._IncludePathList
:
3661 self
._IncludePathList
.append(Inc
)
3663 Inc
= path
.join(Inc
, self
.Arch
.capitalize())
3664 if os
.path
.exists(Inc
) and Inc
not in self
._IncludePathList
:
3665 self
._IncludePathList
.append(Inc
)
3666 # Edk module needs to put DEBUG_DIR at the end of search path and not to use SOURCE_DIR all the time
3667 self
._IncludePathList
.append(self
.DebugDir
)
3669 self
._IncludePathList
.append(self
.MetaFile
.Dir
)
3670 self
._IncludePathList
.append(self
.DebugDir
)
3672 for Package
in self
.Module
.Packages
:
3673 PackageDir
= mws
.join(self
.WorkspaceDir
, Package
.MetaFile
.Dir
)
3674 if PackageDir
not in self
._IncludePathList
:
3675 self
._IncludePathList
.append(PackageDir
)
3676 IncludesList
= Package
.Includes
3677 if Package
._PrivateIncludes
:
3678 if not self
.MetaFile
.Path
.startswith(PackageDir
):
3679 IncludesList
= list(set(Package
.Includes
).difference(set(Package
._PrivateIncludes
)))
3680 for Inc
in IncludesList
:
3681 if Inc
not in self
._IncludePathList
:
3682 self
._IncludePathList
.append(str(Inc
))
3683 return self
._IncludePathList
3685 def _GetIncludePathLength(self
):
3686 self
._IncludePathLength
= 0
3687 if self
._IncludePathList
:
3688 for inc
in self
._IncludePathList
:
3689 self
._IncludePathLength
+= len(' ' + inc
)
3690 return self
._IncludePathLength
3692 ## Get HII EX PCDs which maybe used by VFR
3694 # efivarstore used by VFR may relate with HII EX PCDs
3695 # Get the variable name and GUID from efivarstore and HII EX PCD
3696 # List the HII EX PCDs in As Built INF if both name and GUID match.
3698 # @retval list HII EX PCDs
3700 def _GetPcdsMaybeUsedByVfr(self
):
3701 if not self
.SourceFileList
:
3705 for SrcFile
in self
.SourceFileList
:
3706 if SrcFile
.Ext
.lower() != '.vfr':
3708 Vfri
= os
.path
.join(self
.OutputDir
, SrcFile
.BaseName
+ '.i')
3709 if not os
.path
.exists(Vfri
):
3711 VfriFile
= open(Vfri
, 'r')
3712 Content
= VfriFile
.read()
3714 Pos
= Content
.find('efivarstore')
3717 # Make sure 'efivarstore' is the start of efivarstore statement
3718 # In case of the value of 'name' (name = efivarstore) is equal to 'efivarstore'
3721 while Index
>= 0 and Content
[Index
] in ' \t\r\n':
3723 if Index
>= 0 and Content
[Index
] != ';':
3724 Pos
= Content
.find('efivarstore', Pos
+ len('efivarstore'))
3727 # 'efivarstore' must be followed by name and guid
3729 Name
= gEfiVarStoreNamePattern
.search(Content
, Pos
)
3732 Guid
= gEfiVarStoreGuidPattern
.search(Content
, Pos
)
3735 NameArray
= ConvertStringToByteArray('L"' + Name
.group(1) + '"')
3736 NameGuids
.append((NameArray
, GuidStructureStringToGuidString(Guid
.group(1))))
3737 Pos
= Content
.find('efivarstore', Name
.end())
3741 for Pcd
in self
.PlatformInfo
.Platform
.Pcds
.values():
3742 if Pcd
.Type
!= TAB_PCDS_DYNAMIC_EX_HII
:
3744 for SkuName
in Pcd
.SkuInfoList
:
3745 SkuInfo
= Pcd
.SkuInfoList
[SkuName
]
3746 Name
= ConvertStringToByteArray(SkuInfo
.VariableName
)
3747 Value
= GuidValue(SkuInfo
.VariableGuid
, self
.PlatformInfo
.PackageList
, self
.MetaFile
.Path
)
3750 Guid
= GuidStructureStringToGuidString(Value
)
3751 if (Name
, Guid
) in NameGuids
and Pcd
not in HiiExPcds
:
3752 HiiExPcds
.append(Pcd
)
3757 def _GenOffsetBin(self
):
3759 for SourceFile
in self
.Module
.Sources
:
3760 if SourceFile
.Type
.upper() == ".VFR" :
3762 # search the .map file to find the offset of vfr binary in the PE32+/TE file.
3764 VfrUniBaseName
[SourceFile
.BaseName
] = (SourceFile
.BaseName
+ "Bin")
3765 if SourceFile
.Type
.upper() == ".UNI" :
3767 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
3769 VfrUniBaseName
["UniOffsetName"] = (self
.Name
+ "Strings")
3771 if len(VfrUniBaseName
) == 0:
3773 MapFileName
= os
.path
.join(self
.OutputDir
, self
.Name
+ ".map")
3774 EfiFileName
= os
.path
.join(self
.OutputDir
, self
.Name
+ ".efi")
3775 VfrUniOffsetList
= GetVariableOffset(MapFileName
, EfiFileName
, VfrUniBaseName
.values())
3776 if not VfrUniOffsetList
:
3779 OutputName
= '%sOffset.bin' % self
.Name
3780 UniVfrOffsetFileName
= os
.path
.join( self
.OutputDir
, OutputName
)
3783 fInputfile
= open(UniVfrOffsetFileName
, "wb+", 0)
3785 EdkLogger
.error("build", FILE_OPEN_FAILURE
, "File open failed for %s" % UniVfrOffsetFileName
,None)
3787 # Use a instance of StringIO to cache data
3788 fStringIO
= StringIO('')
3790 for Item
in VfrUniOffsetList
:
3791 if (Item
[0].find("Strings") != -1):
3793 # UNI offset in image.
3795 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }
3797 UniGuid
= [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66]
3798 UniGuid
= [chr(ItemGuid
) for ItemGuid
in UniGuid
]
3799 fStringIO
.write(''.join(UniGuid
))
3800 UniValue
= pack ('Q', int (Item
[1], 16))
3801 fStringIO
.write (UniValue
)
3804 # VFR binary offset in image.
3806 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };
3808 VfrGuid
= [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2]
3809 VfrGuid
= [chr(ItemGuid
) for ItemGuid
in VfrGuid
]
3810 fStringIO
.write(''.join(VfrGuid
))
3812 VfrValue
= pack ('Q', int (Item
[1], 16))
3813 fStringIO
.write (VfrValue
)
3815 # write data into file.
3818 fInputfile
.write (fStringIO
.getvalue())
3820 EdkLogger
.error("build", FILE_WRITE_FAILURE
, "Write data to file %s failed, please check whether the "
3821 "file been locked or using by other applications." %UniVfrOffsetFileName
,None)
3827 ## Create AsBuilt INF file the module
3829 def CreateAsBuiltInf(self
):
3830 if self
.IsAsBuiltInfCreated
:
3833 # Skip the following code for EDK I inf
3834 if self
.AutoGenVersion
< 0x00010005:
3837 # Skip the following code for libraries
3841 # Skip the following code for modules with no source files
3842 if self
.SourceFileList
== None or self
.SourceFileList
== []:
3845 # Skip the following code for modules without any binary files
3846 if self
.BinaryFileList
<> None and self
.BinaryFileList
<> []:
3849 ### TODO: How to handles mixed source and binary modules
3851 # Find all DynamicEx and PatchableInModule PCDs used by this module and dependent libraries
3852 # Also find all packages that the DynamicEx PCDs depend on
3857 PcdTokenSpaceList
= []
3858 for Pcd
in self
.ModulePcdList
+ self
.LibraryPcdList
:
3859 if Pcd
.Type
== TAB_PCDS_PATCHABLE_IN_MODULE
:
3860 PatchablePcds
+= [Pcd
]
3861 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, 'PatchableInModule'))
3862 elif Pcd
.Type
in GenC
.gDynamicExPcd
:
3865 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, 'DynamicEx'))
3866 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, 'Dynamic'))
3867 PcdTokenSpaceList
.append(Pcd
.TokenSpaceGuidCName
)
3869 GuidList
.update(self
.GuidList
)
3870 for TokenSpace
in self
.GetGuidsUsedByPcd():
3871 # If token space is not referred by patch PCD or Ex PCD, remove the GUID from GUID list
3872 # The GUIDs in GUIDs section should really be the GUIDs in source INF or referred by Ex an patch PCDs
3873 if TokenSpace
not in PcdTokenSpaceList
and TokenSpace
in GuidList
:
3874 GuidList
.pop(TokenSpace
)
3875 CheckList
= (GuidList
, self
.PpiList
, self
.ProtocolList
, PcdCheckList
)
3876 for Package
in self
.DerivedPackageList
:
3877 if Package
in Packages
:
3879 BeChecked
= (Package
.Guids
, Package
.Ppis
, Package
.Protocols
, Package
.Pcds
)
3881 for Index
in range(len(BeChecked
)):
3882 for Item
in CheckList
[Index
]:
3883 if Item
in BeChecked
[Index
]:
3884 Packages
+= [Package
]
3889 VfrPcds
= self
._GetPcdsMaybeUsedByVfr
()
3890 for Pkg
in self
.PlatformInfo
.PackageList
:
3893 for VfrPcd
in VfrPcds
:
3894 if ((VfrPcd
.TokenCName
, VfrPcd
.TokenSpaceGuidCName
, 'DynamicEx') in Pkg
.Pcds
or
3895 (VfrPcd
.TokenCName
, VfrPcd
.TokenSpaceGuidCName
, 'Dynamic') in Pkg
.Pcds
):
3899 ModuleType
= self
.ModuleType
3900 if ModuleType
== 'UEFI_DRIVER' and self
.DepexGenerated
:
3901 ModuleType
= 'DXE_DRIVER'
3904 if self
.PcdIsDriver
!= '':
3905 DriverType
= self
.PcdIsDriver
3908 MDefs
= self
.Module
.Defines
3911 'module_name' : self
.Name
,
3912 'module_guid' : Guid
,
3913 'module_module_type' : ModuleType
,
3914 'module_version_string' : [MDefs
['VERSION_STRING']] if 'VERSION_STRING' in MDefs
else [],
3915 'pcd_is_driver_string' : [],
3916 'module_uefi_specification_version' : [],
3917 'module_pi_specification_version' : [],
3918 'module_entry_point' : self
.Module
.ModuleEntryPointList
,
3919 'module_unload_image' : self
.Module
.ModuleUnloadImageList
,
3920 'module_constructor' : self
.Module
.ConstructorList
,
3921 'module_destructor' : self
.Module
.DestructorList
,
3922 'module_shadow' : [MDefs
['SHADOW']] if 'SHADOW' in MDefs
else [],
3923 'module_pci_vendor_id' : [MDefs
['PCI_VENDOR_ID']] if 'PCI_VENDOR_ID' in MDefs
else [],
3924 'module_pci_device_id' : [MDefs
['PCI_DEVICE_ID']] if 'PCI_DEVICE_ID' in MDefs
else [],
3925 'module_pci_class_code' : [MDefs
['PCI_CLASS_CODE']] if 'PCI_CLASS_CODE' in MDefs
else [],
3926 'module_pci_revision' : [MDefs
['PCI_REVISION']] if 'PCI_REVISION' in MDefs
else [],
3927 'module_build_number' : [MDefs
['BUILD_NUMBER']] if 'BUILD_NUMBER' in MDefs
else [],
3928 'module_spec' : [MDefs
['SPEC']] if 'SPEC' in MDefs
else [],
3929 'module_uefi_hii_resource_section' : [MDefs
['UEFI_HII_RESOURCE_SECTION']] if 'UEFI_HII_RESOURCE_SECTION' in MDefs
else [],
3930 'module_uni_file' : [MDefs
['MODULE_UNI_FILE']] if 'MODULE_UNI_FILE' in MDefs
else [],
3931 'module_arch' : self
.Arch
,
3932 'package_item' : ['%s' % (Package
.MetaFile
.File
.replace('\\', '/')) for Package
in Packages
],
3934 'patchablepcd_item' : [],
3936 'protocol_item' : [],
3940 'libraryclasses_item' : []
3943 if 'MODULE_UNI_FILE' in MDefs
:
3944 UNIFile
= os
.path
.join(self
.MetaFile
.Dir
, MDefs
['MODULE_UNI_FILE'])
3945 if os
.path
.isfile(UNIFile
):
3946 shutil
.copy2(UNIFile
, self
.OutputDir
)
3948 if self
.AutoGenVersion
> int(gInfSpecVersion
, 0):
3949 AsBuiltInfDict
['module_inf_version'] = '0x%08x' % self
.AutoGenVersion
3951 AsBuiltInfDict
['module_inf_version'] = gInfSpecVersion
3954 AsBuiltInfDict
['pcd_is_driver_string'] += [DriverType
]
3956 if 'UEFI_SPECIFICATION_VERSION' in self
.Specification
:
3957 AsBuiltInfDict
['module_uefi_specification_version'] += [self
.Specification
['UEFI_SPECIFICATION_VERSION']]
3958 if 'PI_SPECIFICATION_VERSION' in self
.Specification
:
3959 AsBuiltInfDict
['module_pi_specification_version'] += [self
.Specification
['PI_SPECIFICATION_VERSION']]
3961 OutputDir
= self
.OutputDir
.replace('\\', '/').strip('/')
3962 self
.OutputFile
= []
3963 for Item
in self
.CodaTargetList
:
3964 File
= Item
.Target
.Path
.replace('\\', '/').strip('/').replace(OutputDir
, '').strip('/')
3965 if File
not in self
.OutputFile
:
3966 self
.OutputFile
.append(File
)
3967 if Item
.Target
.Ext
.lower() == '.aml':
3968 AsBuiltInfDict
['binary_item'] += ['ASL|' + File
]
3969 elif Item
.Target
.Ext
.lower() == '.acpi':
3970 AsBuiltInfDict
['binary_item'] += ['ACPI|' + File
]
3971 elif Item
.Target
.Ext
.lower() == '.efi':
3972 AsBuiltInfDict
['binary_item'] += ['PE32|' + self
.Name
+ '.efi']
3974 AsBuiltInfDict
['binary_item'] += ['BIN|' + File
]
3975 if self
.DepexGenerated
:
3976 if self
.Name
+ '.depex' not in self
.OutputFile
:
3977 self
.OutputFile
.append(self
.Name
+ '.depex')
3978 if self
.ModuleType
in ['PEIM']:
3979 AsBuiltInfDict
['binary_item'] += ['PEI_DEPEX|' + self
.Name
+ '.depex']
3980 if self
.ModuleType
in ['DXE_DRIVER', 'DXE_RUNTIME_DRIVER', 'DXE_SAL_DRIVER', 'UEFI_DRIVER']:
3981 AsBuiltInfDict
['binary_item'] += ['DXE_DEPEX|' + self
.Name
+ '.depex']
3982 if self
.ModuleType
in ['DXE_SMM_DRIVER']:
3983 AsBuiltInfDict
['binary_item'] += ['SMM_DEPEX|' + self
.Name
+ '.depex']
3985 Bin
= self
._GenOffsetBin
()
3987 AsBuiltInfDict
['binary_item'] += ['BIN|%s' % Bin
]
3988 if Bin
not in self
.OutputFile
:
3989 self
.OutputFile
.append(Bin
)
3991 for Root
, Dirs
, Files
in os
.walk(OutputDir
):
3993 if File
.lower().endswith('.pdb'):
3994 AsBuiltInfDict
['binary_item'] += ['DISPOSABLE|' + File
]
3995 if File
not in self
.OutputFile
:
3996 self
.OutputFile
.append(File
)
3997 HeaderComments
= self
.Module
.HeaderComments
3999 for Index
in range(len(HeaderComments
)):
4000 if HeaderComments
[Index
].find('@BinaryHeader') != -1:
4001 HeaderComments
[Index
] = HeaderComments
[Index
].replace('@BinaryHeader', '@file')
4004 AsBuiltInfDict
['header_comments'] = '\n'.join(HeaderComments
[StartPos
:]).replace(':#', '://')
4005 AsBuiltInfDict
['tail_comments'] = '\n'.join(self
.Module
.TailComments
)
4008 (self
.ProtocolList
, self
._ProtocolComments
, 'protocol_item'),
4009 (self
.PpiList
, self
._PpiComments
, 'ppi_item'),
4010 (GuidList
, self
._GuidComments
, 'guid_item')
4012 for Item
in GenList
:
4013 for CName
in Item
[0]:
4015 if CName
in Item
[1]:
4016 Comments
= '\n '.join(Item
[1][CName
])
4019 Entry
= Comments
+ '\n ' + CName
4020 AsBuiltInfDict
[Item
[2]].append(Entry
)
4021 PatchList
= parsePcdInfoFromMapFile(
4022 os
.path
.join(self
.OutputDir
, self
.Name
+ '.map'),
4023 os
.path
.join(self
.OutputDir
, self
.Name
+ '.efi')
4026 for Pcd
in PatchablePcds
:
4027 TokenCName
= Pcd
.TokenCName
4028 for PcdItem
in GlobalData
.MixedPcd
:
4029 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
4030 TokenCName
= PcdItem
[0]
4032 for PatchPcd
in PatchList
:
4033 if TokenCName
== PatchPcd
[0]:
4038 if Pcd
.DatumType
== 'BOOLEAN':
4039 BoolValue
= Pcd
.DefaultValue
.upper()
4040 if BoolValue
== 'TRUE':
4041 Pcd
.DefaultValue
= '1'
4042 elif BoolValue
== 'FALSE':
4043 Pcd
.DefaultValue
= '0'
4045 if Pcd
.DatumType
!= 'VOID*':
4046 HexFormat
= '0x%02x'
4047 if Pcd
.DatumType
== 'UINT16':
4048 HexFormat
= '0x%04x'
4049 elif Pcd
.DatumType
== 'UINT32':
4050 HexFormat
= '0x%08x'
4051 elif Pcd
.DatumType
== 'UINT64':
4052 HexFormat
= '0x%016x'
4053 PcdValue
= HexFormat
% int(Pcd
.DefaultValue
, 0)
4055 if Pcd
.MaxDatumSize
== None or Pcd
.MaxDatumSize
== '':
4056 EdkLogger
.error("build", AUTOGEN_ERROR
,
4057 "Unknown [MaxDatumSize] of PCD [%s.%s]" % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
4059 ArraySize
= int(Pcd
.MaxDatumSize
, 0)
4060 PcdValue
= Pcd
.DefaultValue
4061 if PcdValue
[0] != '{':
4063 if PcdValue
[0] == 'L':
4065 PcdValue
= PcdValue
.lstrip('L')
4066 PcdValue
= eval(PcdValue
)
4068 for Index
in range(0, len(PcdValue
)):
4070 CharVal
= ord(PcdValue
[Index
])
4071 NewValue
= NewValue
+ '0x%02x' % (CharVal
& 0x00FF) + ', ' \
4072 + '0x%02x' % (CharVal
>> 8) + ', '
4074 NewValue
= NewValue
+ '0x%02x' % (ord(PcdValue
[Index
]) % 0x100) + ', '
4077 Padding
= Padding
* 2
4078 ArraySize
= ArraySize
/ 2
4079 if ArraySize
< (len(PcdValue
) + 1):
4080 EdkLogger
.error("build", AUTOGEN_ERROR
,
4081 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
4083 if ArraySize
> len(PcdValue
) + 1:
4084 NewValue
= NewValue
+ Padding
* (ArraySize
- len(PcdValue
) - 1)
4085 PcdValue
= NewValue
+ Padding
.strip().rstrip(',') + '}'
4086 elif len(PcdValue
.split(',')) <= ArraySize
:
4087 PcdValue
= PcdValue
.rstrip('}') + ', 0x00' * (ArraySize
- len(PcdValue
.split(',')))
4090 EdkLogger
.error("build", AUTOGEN_ERROR
,
4091 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
4093 PcdItem
= '%s.%s|%s|0x%X' % \
4094 (Pcd
.TokenSpaceGuidCName
, TokenCName
, PcdValue
, PatchPcd
[1])
4096 if (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in self
._PcdComments
:
4097 PcdComments
= '\n '.join(self
._PcdComments
[Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
])
4099 PcdItem
= PcdComments
+ '\n ' + PcdItem
4100 AsBuiltInfDict
['patchablepcd_item'].append(PcdItem
)
4103 for Pcd
in Pcds
+ VfrPcds
:
4108 TokenCName
= Pcd
.TokenCName
4109 for PcdItem
in GlobalData
.MixedPcd
:
4110 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
4111 TokenCName
= PcdItem
[0]
4113 if Pcd
.Type
== TAB_PCDS_DYNAMIC_EX_HII
:
4114 for SkuName
in Pcd
.SkuInfoList
:
4115 SkuInfo
= Pcd
.SkuInfoList
[SkuName
]
4116 SkuId
= SkuInfo
.SkuId
4117 HiiInfo
= '## %s|%s|%s' % (SkuInfo
.VariableName
, SkuInfo
.VariableGuid
, SkuInfo
.VariableOffset
)
4121 # Don't generate duplicated HII PCD
4123 if (SkuId
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in HiiPcds
:
4126 HiiPcds
.append((SkuId
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
4127 if (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in self
._PcdComments
:
4128 PcdCommentList
= self
._PcdComments
[Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
][:]
4132 for Index
, Comment
in enumerate(PcdCommentList
):
4133 for Usage
in UsageList
:
4134 if Comment
.find(Usage
) != -1:
4138 if UsageIndex
!= -1:
4139 PcdCommentList
[UsageIndex
] = '## %s %s %s' % (UsageStr
, HiiInfo
, PcdCommentList
[UsageIndex
].replace(UsageStr
, ''))
4141 PcdCommentList
.append('## UNDEFINED ' + HiiInfo
)
4142 PcdComments
= '\n '.join(PcdCommentList
)
4143 PcdEntry
= Pcd
.TokenSpaceGuidCName
+ '.' + TokenCName
4145 PcdEntry
= PcdComments
+ '\n ' + PcdEntry
4146 AsBuiltInfDict
['pcd_item'] += [PcdEntry
]
4147 for Item
in self
.BuildOption
:
4148 if 'FLAGS' in self
.BuildOption
[Item
]:
4149 AsBuiltInfDict
['flags_item'] += ['%s:%s_%s_%s_%s_FLAGS = %s' % (self
.ToolChainFamily
, self
.BuildTarget
, self
.ToolChain
, self
.Arch
, Item
, self
.BuildOption
[Item
]['FLAGS'].strip())]
4151 # Generated LibraryClasses section in comments.
4152 for Library
in self
.LibraryAutoGenList
:
4153 AsBuiltInfDict
['libraryclasses_item'] += [Library
.MetaFile
.File
.replace('\\', '/')]
4155 # Generated UserExtensions TianoCore section.
4156 # All tianocore user extensions are copied.
4158 for TianoCore
in self
._GetTianoCoreUserExtensionList
():
4159 UserExtStr
+= '\n'.join(TianoCore
)
4160 ExtensionFile
= os
.path
.join(self
.MetaFile
.Dir
, TianoCore
[1])
4161 if os
.path
.isfile(ExtensionFile
):
4162 shutil
.copy2(ExtensionFile
, self
.OutputDir
)
4163 AsBuiltInfDict
['userextension_tianocore_item'] = UserExtStr
4165 # Generated depex expression section in comments.
4166 AsBuiltInfDict
['depexsection_item'] = ''
4167 DepexExpresion
= self
._GetDepexExpresionString
()
4169 AsBuiltInfDict
['depexsection_item'] = DepexExpresion
4171 AsBuiltInf
= TemplateString()
4172 AsBuiltInf
.Append(gAsBuiltInfHeaderString
.Replace(AsBuiltInfDict
))
4174 SaveFileOnChange(os
.path
.join(self
.OutputDir
, self
.Name
+ '.inf'), str(AsBuiltInf
), False)
4176 self
.IsAsBuiltInfCreated
= True
4177 if GlobalData
.gBinCacheDest
:
4178 self
.CopyModuleToCache()
4180 def CopyModuleToCache(self
):
4181 FileDir
= path
.join(GlobalData
.gBinCacheDest
, self
.Arch
, self
.SourceDir
, self
.MetaFile
.BaseName
)
4182 CreateDirectory (FileDir
)
4183 HashFile
= path
.join(self
.BuildDir
, self
.Name
+ '.hash')
4184 ModuleFile
= path
.join(self
.OutputDir
, self
.Name
+ '.inf')
4185 if os
.path
.exists(HashFile
):
4186 shutil
.copy2(HashFile
, FileDir
)
4187 if os
.path
.exists(ModuleFile
):
4188 shutil
.copy2(ModuleFile
, FileDir
)
4190 for File
in self
.OutputFile
:
4191 if not os
.path
.isabs(File
):
4192 File
= os
.path
.join(self
.OutputDir
, File
)
4193 if os
.path
.exists(File
):
4194 shutil
.copy2(File
, FileDir
)
4196 def AttemptModuleCacheCopy(self
):
4197 if self
.IsBinaryModule
:
4199 FileDir
= path
.join(GlobalData
.gBinCacheSource
, self
.Arch
, self
.SourceDir
, self
.MetaFile
.BaseName
)
4200 HashFile
= path
.join(FileDir
, self
.Name
+ '.hash')
4201 if os
.path
.exists(HashFile
):
4202 f
= open(HashFile
, 'r')
4203 CacheHash
= f
.read()
4205 if GlobalData
.gModuleHash
[self
.Arch
][self
.Name
]:
4206 if CacheHash
== GlobalData
.gModuleHash
[self
.Arch
][self
.Name
]:
4207 for root
, dir, files
in os
.walk(FileDir
):
4209 if self
.Name
+ '.hash' in f
:
4210 shutil
.copy2(HashFile
, self
.BuildDir
)
4212 File
= path
.join(root
, f
)
4213 shutil
.copy2(File
, self
.OutputDir
)
4214 if self
.Name
== "PcdPeim" or self
.Name
== "PcdDxe":
4215 CreatePcdDatabaseCode(self
, TemplateString(), TemplateString())
4219 ## Create makefile for the module and its dependent libraries
4221 # @param CreateLibraryMakeFile Flag indicating if or not the makefiles of
4222 # dependent libraries will be created
4224 def CreateMakeFile(self
, CreateLibraryMakeFile
=True):
4225 # Ignore generating makefile when it is a binary module
4226 if self
.IsBinaryModule
:
4229 if self
.IsMakeFileCreated
:
4234 if not self
.IsLibrary
and CreateLibraryMakeFile
:
4235 for LibraryAutoGen
in self
.LibraryAutoGenList
:
4236 LibraryAutoGen
.CreateMakeFile()
4238 if len(self
.CustomMakefile
) == 0:
4239 Makefile
= GenMake
.ModuleMakefile(self
)
4241 Makefile
= GenMake
.CustomMakefile(self
)
4242 if Makefile
.Generate():
4243 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated makefile for module %s [%s]" %
4244 (self
.Name
, self
.Arch
))
4246 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of makefile for module %s [%s]" %
4247 (self
.Name
, self
.Arch
))
4249 self
.CreateTimeStamp(Makefile
)
4250 self
.IsMakeFileCreated
= True
4252 def CopyBinaryFiles(self
):
4253 for File
in self
.Module
.Binaries
:
4255 DstPath
= os
.path
.join(self
.OutputDir
, os
.path
.basename(SrcPath
))
4256 CopyLongFilePath(SrcPath
, DstPath
)
4257 ## Create autogen code for the module and its dependent libraries
4259 # @param CreateLibraryCodeFile Flag indicating if or not the code of
4260 # dependent libraries will be created
4262 def CreateCodeFile(self
, CreateLibraryCodeFile
=True):
4263 if self
.IsCodeFileCreated
:
4268 # Need to generate PcdDatabase even PcdDriver is binarymodule
4269 if self
.IsBinaryModule
and self
.PcdIsDriver
!= '':
4270 CreatePcdDatabaseCode(self
, TemplateString(), TemplateString())
4272 if self
.IsBinaryModule
:
4274 self
.CopyBinaryFiles()
4277 if not self
.IsLibrary
and CreateLibraryCodeFile
:
4278 for LibraryAutoGen
in self
.LibraryAutoGenList
:
4279 LibraryAutoGen
.CreateCodeFile()
4282 IgoredAutoGenList
= []
4284 for File
in self
.AutoGenFileList
:
4285 if GenC
.Generate(File
.Path
, self
.AutoGenFileList
[File
], File
.IsBinary
):
4286 #Ignore Edk AutoGen.c
4287 if self
.AutoGenVersion
< 0x00010005 and File
.Name
== 'AutoGen.c':
4290 AutoGenList
.append(str(File
))
4292 IgoredAutoGenList
.append(str(File
))
4294 # Skip the following code for EDK I inf
4295 if self
.AutoGenVersion
< 0x00010005:
4298 for ModuleType
in self
.DepexList
:
4299 # Ignore empty [depex] section or [depex] section for "USER_DEFINED" module
4300 if len(self
.DepexList
[ModuleType
]) == 0 or ModuleType
== "USER_DEFINED":
4303 Dpx
= GenDepex
.DependencyExpression(self
.DepexList
[ModuleType
], ModuleType
, True)
4304 DpxFile
= gAutoGenDepexFileName
% {"module_name" : self
.Name
}
4306 if len(Dpx
.PostfixNotation
) <> 0:
4307 self
.DepexGenerated
= True
4309 if Dpx
.Generate(path
.join(self
.OutputDir
, DpxFile
)):
4310 AutoGenList
.append(str(DpxFile
))
4312 IgoredAutoGenList
.append(str(DpxFile
))
4314 if IgoredAutoGenList
== []:
4315 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] files for module %s [%s]" %
4316 (" ".join(AutoGenList
), self
.Name
, self
.Arch
))
4317 elif AutoGenList
== []:
4318 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of [%s] files for module %s [%s]" %
4319 (" ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
4321 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] (skipped %s) files for module %s [%s]" %
4322 (" ".join(AutoGenList
), " ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
4324 self
.IsCodeFileCreated
= True
4327 ## Summarize the ModuleAutoGen objects of all libraries used by this module
4328 def _GetLibraryAutoGenList(self
):
4329 if self
._LibraryAutoGenList
== None:
4330 self
._LibraryAutoGenList
= []
4331 for Library
in self
.DependentLibraryList
:
4338 self
.PlatformInfo
.MetaFile
4340 if La
not in self
._LibraryAutoGenList
:
4341 self
._LibraryAutoGenList
.append(La
)
4342 for Lib
in La
.CodaTargetList
:
4343 self
._ApplyBuildRule
(Lib
.Target
, TAB_UNKNOWN_FILE
)
4344 return self
._LibraryAutoGenList
4346 def GenModuleHash(self
):
4347 if self
.Arch
not in GlobalData
.gModuleHash
:
4348 GlobalData
.gModuleHash
[self
.Arch
] = {}
4350 # Add Platform level hash
4351 m
.update(GlobalData
.gPlatformHash
)
4352 # Add Package level hash
4353 if self
.DependentPackageList
:
4354 for Pkg
in self
.DependentPackageList
:
4355 if Pkg
.PackageName
in GlobalData
.gPackageHash
[self
.Arch
]:
4356 m
.update(GlobalData
.gPackageHash
[self
.Arch
][Pkg
.PackageName
])
4359 if self
.LibraryAutoGenList
:
4360 for Lib
in self
.LibraryAutoGenList
:
4361 if Lib
.Name
not in GlobalData
.gModuleHash
[self
.Arch
]:
4363 m
.update(GlobalData
.gModuleHash
[self
.Arch
][Lib
.Name
])
4366 f
= open(str(self
.MetaFile
), 'r')
4370 # Add Module's source files
4371 if self
.SourceFileList
:
4372 for File
in self
.SourceFileList
:
4373 f
= open(str(File
), 'r')
4378 ModuleHashFile
= path
.join(self
.BuildDir
, self
.Name
+ ".hash")
4379 if self
.Name
not in GlobalData
.gModuleHash
[self
.Arch
]:
4380 GlobalData
.gModuleHash
[self
.Arch
][self
.Name
] = m
.hexdigest()
4381 if GlobalData
.gBinCacheSource
:
4382 CacheValid
= self
.AttemptModuleCacheCopy()
4385 return SaveFileOnChange(ModuleHashFile
, m
.hexdigest(), True)
4387 ## Decide whether we can skip the ModuleAutoGen process
4388 def CanSkipbyHash(self
):
4389 if GlobalData
.gUseHashCache
:
4390 return not self
.GenModuleHash()
4392 ## Decide whether we can skip the ModuleAutoGen process
4393 # If any source file is newer than the module than we cannot skip
4396 if not os
.path
.exists(self
.GetTimeStampPath()):
4398 #last creation time of the module
4399 DstTimeStamp
= os
.stat(self
.GetTimeStampPath())[8]
4401 SrcTimeStamp
= self
.Workspace
._SrcTimeStamp
4402 if SrcTimeStamp
> DstTimeStamp
:
4405 with
open(self
.GetTimeStampPath(),'r') as f
:
4407 source
= source
.rstrip('\n')
4408 if not os
.path
.exists(source
):
4410 if source
not in ModuleAutoGen
.TimeDict
:
4411 ModuleAutoGen
.TimeDict
[source
] = os
.stat(source
)[8]
4412 if ModuleAutoGen
.TimeDict
[source
] > DstTimeStamp
:
4416 def GetTimeStampPath(self
):
4417 if self
._TimeStampPath
== None:
4418 self
._TimeStampPath
= os
.path
.join(self
.MakeFileDir
, 'AutoGenTimeStamp')
4419 return self
._TimeStampPath
4420 def CreateTimeStamp(self
, Makefile
):
4424 FileSet
.add (self
.MetaFile
.Path
)
4426 for SourceFile
in self
.Module
.Sources
:
4427 FileSet
.add (SourceFile
.Path
)
4429 for Lib
in self
.DependentLibraryList
:
4430 FileSet
.add (Lib
.MetaFile
.Path
)
4432 for f
in self
.AutoGenDepSet
:
4433 FileSet
.add (f
.Path
)
4435 if os
.path
.exists (self
.GetTimeStampPath()):
4436 os
.remove (self
.GetTimeStampPath())
4437 with
open(self
.GetTimeStampPath(), 'w+') as file:
4441 Module
= property(_GetModule
)
4442 Name
= property(_GetBaseName
)
4443 Guid
= property(_GetGuid
)
4444 Version
= property(_GetVersion
)
4445 ModuleType
= property(_GetModuleType
)
4446 ComponentType
= property(_GetComponentType
)
4447 BuildType
= property(_GetBuildType
)
4448 PcdIsDriver
= property(_GetPcdIsDriver
)
4449 AutoGenVersion
= property(_GetAutoGenVersion
)
4450 Macros
= property(_GetMacros
)
4451 Specification
= property(_GetSpecification
)
4453 IsLibrary
= property(_IsLibrary
)
4454 IsBinaryModule
= property(_IsBinaryModule
)
4455 BuildDir
= property(_GetBuildDir
)
4456 OutputDir
= property(_GetOutputDir
)
4457 DebugDir
= property(_GetDebugDir
)
4458 MakeFileDir
= property(_GetMakeFileDir
)
4459 CustomMakefile
= property(_GetCustomMakefile
)
4461 IncludePathList
= property(_GetIncludePathList
)
4462 IncludePathLength
= property(_GetIncludePathLength
)
4463 AutoGenFileList
= property(_GetAutoGenFileList
)
4464 UnicodeFileList
= property(_GetUnicodeFileList
)
4465 VfrFileList
= property(_GetVfrFileList
)
4466 SourceFileList
= property(_GetSourceFileList
)
4467 BinaryFileList
= property(_GetBinaryFiles
) # FileType : [File List]
4468 Targets
= property(_GetTargets
)
4469 IntroTargetList
= property(_GetIntroTargetList
)
4470 CodaTargetList
= property(_GetFinalTargetList
)
4471 FileTypes
= property(_GetFileTypes
)
4472 BuildRules
= property(_GetBuildRules
)
4473 IdfFileList
= property(_GetIdfFileList
)
4475 DependentPackageList
= property(_GetDependentPackageList
)
4476 DependentLibraryList
= property(_GetLibraryList
)
4477 LibraryAutoGenList
= property(_GetLibraryAutoGenList
)
4478 DerivedPackageList
= property(_GetDerivedPackageList
)
4480 ModulePcdList
= property(_GetModulePcdList
)
4481 LibraryPcdList
= property(_GetLibraryPcdList
)
4482 GuidList
= property(_GetGuidList
)
4483 ProtocolList
= property(_GetProtocolList
)
4484 PpiList
= property(_GetPpiList
)
4485 DepexList
= property(_GetDepexTokenList
)
4486 DxsFile
= property(_GetDxsFile
)
4487 DepexExpressionList
= property(_GetDepexExpressionTokenList
)
4488 BuildOption
= property(_GetModuleBuildOption
)
4489 BuildOptionIncPathList
= property(_GetBuildOptionIncPathList
)
4490 BuildCommand
= property(_GetBuildCommand
)
4492 FixedAtBuildPcds
= property(_GetFixedAtBuildPcds
)
4494 # This acts like the main() function for the script, unless it is 'import'ed into another script.
4495 if __name__
== '__main__':