2 # Generate AutoGen.h, AutoGen.c and *.depex files
4 # Copyright (c) 2007 - 2017, Intel Corporation. All rights reserved.<BR>
5 # This program and the accompanying materials
6 # are licensed and made available under the terms and conditions of the BSD License
7 # which accompanies this distribution. The full text of the license may be found at
8 # http://opensource.org/licenses/bsd-license.php
10 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 import Common
.LongFilePathOs
as os
18 import os
.path
as path
25 from StringIO
import StringIO
27 from StrGather
import *
28 from BuildEngine
import BuildRule
30 from Common
.LongFilePathSupport
import CopyLongFilePath
31 from Common
.BuildToolError
import *
32 from Common
.DataType
import *
33 from Common
.Misc
import *
34 from Common
.String
import *
35 import Common
.GlobalData
as GlobalData
36 from GenFds
.FdfParser
import *
37 from CommonDataClass
.CommonClass
import SkuInfoClass
38 from Workspace
.BuildClassObject
import *
39 from GenPatchPcdTable
.GenPatchPcdTable
import parsePcdInfoFromMapFile
40 import Common
.VpdInfoFile
as VpdInfoFile
41 from GenPcdDb
import CreatePcdDatabaseCode
42 from Workspace
.MetaFileCommentParser
import UsageList
43 from Common
.MultipleWorkspace
import MultipleWorkspace
as mws
44 import InfSectionParser
48 ## Regular expression for splitting Dependency Expression string into tokens
49 gDepexTokenPattern
= re
.compile("(\(|\)|\w+| \S+\.inf)")
52 # Match name = variable
54 gEfiVarStoreNamePattern
= re
.compile("\s*name\s*=\s*(\w+)")
56 # The format of guid in efivarstore statement likes following and must be correct:
57 # guid = {0xA04A27f4, 0xDF00, 0x4D42, {0xB5, 0x52, 0x39, 0x51, 0x13, 0x02, 0x11, 0x3D}}
59 gEfiVarStoreGuidPattern
= re
.compile("\s*guid\s*=\s*({.*?{.*?}\s*})")
61 ## Mapping Makefile type
62 gMakeTypeMap
= {"MSFT":"nmake", "GCC":"gmake"}
65 ## Build rule configuration file
66 gDefaultBuildRuleFile
= 'build_rule.txt'
68 ## Tools definition configuration file
69 gDefaultToolsDefFile
= 'tools_def.txt'
71 ## Build rule default version
72 AutoGenReqBuildRuleVerNum
= "0.1"
74 ## default file name for AutoGen
75 gAutoGenCodeFileName
= "AutoGen.c"
76 gAutoGenHeaderFileName
= "AutoGen.h"
77 gAutoGenStringFileName
= "%(module_name)sStrDefs.h"
78 gAutoGenStringFormFileName
= "%(module_name)sStrDefs.hpk"
79 gAutoGenDepexFileName
= "%(module_name)s.depex"
80 gAutoGenImageDefFileName
= "%(module_name)sImgDefs.h"
81 gAutoGenIdfFileName
= "%(module_name)sIdf.hpk"
82 gInfSpecVersion
= "0x00010017"
85 # Template string to generic AsBuilt INF
87 gAsBuiltInfHeaderString
= TemplateString("""${header_comments}
93 INF_VERSION = ${module_inf_version}
94 BASE_NAME = ${module_name}
95 FILE_GUID = ${module_guid}
96 MODULE_TYPE = ${module_module_type}${BEGIN}
97 VERSION_STRING = ${module_version_string}${END}${BEGIN}
98 PCD_IS_DRIVER = ${pcd_is_driver_string}${END}${BEGIN}
99 UEFI_SPECIFICATION_VERSION = ${module_uefi_specification_version}${END}${BEGIN}
100 PI_SPECIFICATION_VERSION = ${module_pi_specification_version}${END}${BEGIN}
101 ENTRY_POINT = ${module_entry_point}${END}${BEGIN}
102 UNLOAD_IMAGE = ${module_unload_image}${END}${BEGIN}
103 CONSTRUCTOR = ${module_constructor}${END}${BEGIN}
104 DESTRUCTOR = ${module_destructor}${END}${BEGIN}
105 SHADOW = ${module_shadow}${END}${BEGIN}
106 PCI_VENDOR_ID = ${module_pci_vendor_id}${END}${BEGIN}
107 PCI_DEVICE_ID = ${module_pci_device_id}${END}${BEGIN}
108 PCI_CLASS_CODE = ${module_pci_class_code}${END}${BEGIN}
109 PCI_REVISION = ${module_pci_revision}${END}${BEGIN}
110 BUILD_NUMBER = ${module_build_number}${END}${BEGIN}
111 SPEC = ${module_spec}${END}${BEGIN}
112 UEFI_HII_RESOURCE_SECTION = ${module_uefi_hii_resource_section}${END}${BEGIN}
113 MODULE_UNI_FILE = ${module_uni_file}${END}
115 [Packages.${module_arch}]${BEGIN}
116 ${package_item}${END}
118 [Binaries.${module_arch}]${BEGIN}
121 [PatchPcd.${module_arch}]${BEGIN}
125 [Protocols.${module_arch}]${BEGIN}
129 [Ppis.${module_arch}]${BEGIN}
133 [Guids.${module_arch}]${BEGIN}
137 [PcdEx.${module_arch}]${BEGIN}
141 [LibraryClasses.${module_arch}]
142 ## @LIB_INSTANCES${BEGIN}
143 # ${libraryclasses_item}${END}
147 ${userextension_tianocore_item}
151 [BuildOptions.${module_arch}]
153 ## ${flags_item}${END}
156 ## Base class for AutoGen
158 # This class just implements the cache mechanism of AutoGen objects.
160 class AutoGen(object):
161 # database to maintain the objects of xxxAutoGen
162 _CACHE_
= {} # (BuildTarget, ToolChain) : {ARCH : {platform file: AutoGen object}}}
166 # @param Class class object of real AutoGen class
167 # (WorkspaceAutoGen, ModuleAutoGen or PlatformAutoGen)
168 # @param Workspace Workspace directory or WorkspaceAutoGen object
169 # @param MetaFile The path of meta file
170 # @param Target Build target
171 # @param Toolchain Tool chain name
172 # @param Arch Target arch
173 # @param *args The specific class related parameters
174 # @param **kwargs The specific class related dict parameters
176 def __new__(Class
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
177 # check if the object has been created
178 Key
= (Target
, Toolchain
)
179 if Key
not in Class
._CACHE
_ or Arch
not in Class
._CACHE
_[Key
] \
180 or MetaFile
not in Class
._CACHE
_[Key
][Arch
]:
181 AutoGenObject
= super(AutoGen
, Class
).__new
__(Class
)
182 # call real constructor
183 if not AutoGenObject
._Init
(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
185 if Key
not in Class
._CACHE
_:
186 Class
._CACHE
_[Key
] = {}
187 if Arch
not in Class
._CACHE
_[Key
]:
188 Class
._CACHE
_[Key
][Arch
] = {}
189 Class
._CACHE
_[Key
][Arch
][MetaFile
] = AutoGenObject
191 AutoGenObject
= Class
._CACHE
_[Key
][Arch
][MetaFile
]
197 # The file path of platform file will be used to represent hash value of this object
199 # @retval int Hash value of the file path of platform file
202 return hash(self
.MetaFile
)
206 # The file path of platform file will be used to represent this object
208 # @retval string String of platform file path
211 return str(self
.MetaFile
)
214 def __eq__(self
, Other
):
215 return Other
and self
.MetaFile
== Other
217 ## Workspace AutoGen class
219 # This class is used mainly to control the whole platform build for different
220 # architecture. This class will generate top level makefile.
222 class WorkspaceAutoGen(AutoGen
):
223 ## Real constructor of WorkspaceAutoGen
225 # This method behaves the same as __init__ except that it needs explicit invoke
226 # (in super class's __new__ method)
228 # @param WorkspaceDir Root directory of workspace
229 # @param ActivePlatform Meta-file of active platform
230 # @param Target Build target
231 # @param Toolchain Tool chain name
232 # @param ArchList List of architecture of current build
233 # @param MetaFileDb Database containing meta-files
234 # @param BuildConfig Configuration of build
235 # @param ToolDefinition Tool chain definitions
236 # @param FlashDefinitionFile File of flash definition
237 # @param Fds FD list to be generated
238 # @param Fvs FV list to be generated
239 # @param Caps Capsule list to be generated
240 # @param SkuId SKU id from command line
242 def _Init(self
, WorkspaceDir
, ActivePlatform
, Target
, Toolchain
, ArchList
, MetaFileDb
,
243 BuildConfig
, ToolDefinition
, FlashDefinitionFile
='', Fds
=None, Fvs
=None, Caps
=None, SkuId
='', UniFlag
=None,
244 Progress
=None, BuildModule
=None):
251 self
.BuildDatabase
= MetaFileDb
252 self
.MetaFile
= ActivePlatform
253 self
.WorkspaceDir
= WorkspaceDir
254 self
.Platform
= self
.BuildDatabase
[self
.MetaFile
, 'COMMON', Target
, Toolchain
]
255 GlobalData
.gActivePlatform
= self
.Platform
256 self
.BuildTarget
= Target
257 self
.ToolChain
= Toolchain
258 self
.ArchList
= ArchList
260 self
.UniFlag
= UniFlag
262 self
.TargetTxt
= BuildConfig
263 self
.ToolDef
= ToolDefinition
264 self
.FdfFile
= FlashDefinitionFile
265 self
.FdTargetList
= Fds
266 self
.FvTargetList
= Fvs
267 self
.CapTargetList
= Caps
268 self
.AutoGenObjectList
= []
269 self
._BuildDir
= None
271 self
._MakeFileDir
= None
272 self
._BuildCommand
= None
274 # there's many relative directory operations, so ...
275 os
.chdir(self
.WorkspaceDir
)
280 if not self
.ArchList
:
281 ArchList
= set(self
.Platform
.SupArchList
)
283 ArchList
= set(self
.ArchList
) & set(self
.Platform
.SupArchList
)
285 EdkLogger
.error("build", PARAMETER_INVALID
,
286 ExtraData
= "Invalid ARCH specified. [Valid ARCH: %s]" % (" ".join(self
.Platform
.SupArchList
)))
287 elif self
.ArchList
and len(ArchList
) != len(self
.ArchList
):
288 SkippedArchList
= set(self
.ArchList
).symmetric_difference(set(self
.Platform
.SupArchList
))
289 EdkLogger
.verbose("\nArch [%s] is ignored because the platform supports [%s] only!"
290 % (" ".join(SkippedArchList
), " ".join(self
.Platform
.SupArchList
)))
291 self
.ArchList
= tuple(ArchList
)
293 # Validate build target
294 if self
.BuildTarget
not in self
.Platform
.BuildTargets
:
295 EdkLogger
.error("build", PARAMETER_INVALID
,
296 ExtraData
="Build target [%s] is not supported by the platform. [Valid target: %s]"
297 % (self
.BuildTarget
, " ".join(self
.Platform
.BuildTargets
)))
300 # parse FDF file to get PCDs in it, if any
302 self
.FdfFile
= self
.Platform
.FlashDefinition
306 EdkLogger
.info('%-16s = %s' % ("Architecture(s)", ' '.join(self
.ArchList
)))
307 EdkLogger
.info('%-16s = %s' % ("Build target", self
.BuildTarget
))
308 EdkLogger
.info('%-16s = %s' % ("Toolchain", self
.ToolChain
))
310 EdkLogger
.info('\n%-24s = %s' % ("Active Platform", self
.Platform
))
312 EdkLogger
.info('%-24s = %s' % ("Active Module", BuildModule
))
315 EdkLogger
.info('%-24s = %s' % ("Flash Image Definition", self
.FdfFile
))
317 EdkLogger
.verbose("\nFLASH_DEFINITION = %s" % self
.FdfFile
)
320 Progress
.Start("\nProcessing meta-data")
324 # Mark now build in AutoGen Phase
326 GlobalData
.gAutoGenPhase
= True
327 Fdf
= FdfParser(self
.FdfFile
.Path
)
329 GlobalData
.gFdfParser
= Fdf
330 GlobalData
.gAutoGenPhase
= False
331 PcdSet
= Fdf
.Profile
.PcdDict
332 if Fdf
.CurrentFdName
and Fdf
.CurrentFdName
in Fdf
.Profile
.FdDict
:
333 FdDict
= Fdf
.Profile
.FdDict
[Fdf
.CurrentFdName
]
334 for FdRegion
in FdDict
.RegionList
:
335 if str(FdRegion
.RegionType
) is 'FILE' and self
.Platform
.VpdToolGuid
in str(FdRegion
.RegionDataList
):
336 if int(FdRegion
.Offset
) % 8 != 0:
337 EdkLogger
.error("build", FORMAT_INVALID
, 'The VPD Base Address %s must be 8-byte aligned.' % (FdRegion
.Offset
))
338 ModuleList
= Fdf
.Profile
.InfList
339 self
.FdfProfile
= Fdf
.Profile
340 for fvname
in self
.FvTargetList
:
341 if fvname
.upper() not in self
.FdfProfile
.FvDict
:
342 EdkLogger
.error("build", OPTION_VALUE_INVALID
,
343 "No such an FV in FDF file: %s" % fvname
)
345 # In DSC file may use FILE_GUID to override the module, then in the Platform.Modules use FILE_GUIDmodule.inf as key,
346 # but the path (self.MetaFile.Path) is the real path
347 for key
in self
.FdfProfile
.InfDict
:
351 for Arch
in self
.ArchList
:
352 Platform_cache
[Arch
] = self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
353 MetaFile_cache
[Arch
] = []
354 for Pkey
in Platform_cache
[Arch
].Modules
.keys():
355 MetaFile_cache
[Arch
].append(Platform_cache
[Arch
].Modules
[Pkey
].MetaFile
)
356 for Inf
in self
.FdfProfile
.InfDict
[key
]:
357 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
358 for Arch
in self
.ArchList
:
359 if ModuleFile
in MetaFile_cache
[Arch
]:
362 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, Target
, Toolchain
]
363 if not ModuleData
.IsBinaryModule
:
364 EdkLogger
.error('build', PARSER_ERROR
, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile
)
367 for Arch
in self
.ArchList
:
369 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
371 for Pkey
in Platform
.Modules
.keys():
372 MetaFileList
.append(Platform
.Modules
[Pkey
].MetaFile
)
373 for Inf
in self
.FdfProfile
.InfDict
[key
]:
374 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
375 if ModuleFile
in MetaFileList
:
377 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, Target
, Toolchain
]
378 if not ModuleData
.IsBinaryModule
:
379 EdkLogger
.error('build', PARSER_ERROR
, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile
)
384 self
.FdfProfile
= None
385 if self
.FdTargetList
:
386 EdkLogger
.info("No flash definition file found. FD [%s] will be ignored." % " ".join(self
.FdTargetList
))
387 self
.FdTargetList
= []
388 if self
.FvTargetList
:
389 EdkLogger
.info("No flash definition file found. FV [%s] will be ignored." % " ".join(self
.FvTargetList
))
390 self
.FvTargetList
= []
391 if self
.CapTargetList
:
392 EdkLogger
.info("No flash definition file found. Capsule [%s] will be ignored." % " ".join(self
.CapTargetList
))
393 self
.CapTargetList
= []
395 # apply SKU and inject PCDs from Flash Definition file
396 for Arch
in self
.ArchList
:
397 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
401 PGen
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
402 if GlobalData
.BuildOptionPcd
:
403 for i
, pcd
in enumerate(GlobalData
.BuildOptionPcd
):
404 if type(pcd
) is tuple:
406 (pcdname
, pcdvalue
) = pcd
.split('=')
408 EdkLogger
.error('build', AUTOGEN_ERROR
, "No Value specified for the PCD %s." % (pcdname
))
410 (TokenSpaceGuidCName
, TokenCName
) = pcdname
.split('.')
414 TokenSpaceGuidCName
= ''
415 HasTokenSpace
= False
416 TokenSpaceGuidCNameList
= []
420 for package
in PGen
.PackageList
:
421 for key
in package
.Pcds
:
422 PcdItem
= package
.Pcds
[key
]
424 if (PcdItem
.TokenCName
, PcdItem
.TokenSpaceGuidCName
) == (TokenCName
, TokenSpaceGuidCName
):
425 PcdDatumType
= PcdItem
.DatumType
426 NewValue
= BuildOptionPcdValueFormat(TokenSpaceGuidCName
, TokenCName
, PcdDatumType
, pcdvalue
)
429 if PcdItem
.TokenCName
== TokenCName
:
430 if not PcdItem
.TokenSpaceGuidCName
in TokenSpaceGuidCNameList
:
431 if len (TokenSpaceGuidCNameList
) < 1:
432 TokenSpaceGuidCNameList
.append(PcdItem
.TokenSpaceGuidCName
)
433 PcdDatumType
= PcdItem
.DatumType
434 TokenSpaceGuidCName
= PcdItem
.TokenSpaceGuidCName
435 NewValue
= BuildOptionPcdValueFormat(TokenSpaceGuidCName
, TokenCName
, PcdDatumType
, pcdvalue
)
441 "The Pcd %s is found under multiple different TokenSpaceGuid: %s and %s." % (TokenCName
, PcdItem
.TokenSpaceGuidCName
, TokenSpaceGuidCNameList
[0])
444 GlobalData
.BuildOptionPcd
[i
] = (TokenSpaceGuidCName
, TokenCName
, NewValue
)
448 EdkLogger
.error('build', AUTOGEN_ERROR
, "The Pcd %s.%s is not found in the DEC file." % (TokenSpaceGuidCName
, TokenCName
))
450 EdkLogger
.error('build', AUTOGEN_ERROR
, "The Pcd %s is not found in the DEC file." % (TokenCName
))
452 for BuildData
in PGen
.BuildDatabase
._CACHE
_.values():
453 if BuildData
.Arch
!= Arch
:
455 if BuildData
.MetaFile
.Ext
== '.dec':
457 for key
in BuildData
.Pcds
:
458 PcdItem
= BuildData
.Pcds
[key
]
459 if (TokenSpaceGuidCName
, TokenCName
) == (PcdItem
.TokenSpaceGuidCName
, PcdItem
.TokenCName
):
460 PcdItem
.DefaultValue
= NewValue
462 if (TokenCName
, TokenSpaceGuidCName
) in PcdSet
:
463 PcdSet
[(TokenCName
, TokenSpaceGuidCName
)] = NewValue
465 SourcePcdDict
= {'DynamicEx':[], 'PatchableInModule':[],'Dynamic':[],'FixedAtBuild':[]}
466 BinaryPcdDict
= {'DynamicEx':[], 'PatchableInModule':[]}
467 SourcePcdDict_Keys
= SourcePcdDict
.keys()
468 BinaryPcdDict_Keys
= BinaryPcdDict
.keys()
470 # generate the SourcePcdDict and BinaryPcdDict
471 for BuildData
in PGen
.BuildDatabase
._CACHE
_.values():
472 if BuildData
.Arch
!= Arch
:
474 if BuildData
.MetaFile
.Ext
== '.inf':
475 for key
in BuildData
.Pcds
:
476 if BuildData
.Pcds
[key
].Pending
:
477 if key
in Platform
.Pcds
:
478 PcdInPlatform
= Platform
.Pcds
[key
]
479 if PcdInPlatform
.Type
not in [None, '']:
480 BuildData
.Pcds
[key
].Type
= PcdInPlatform
.Type
482 if BuildData
.MetaFile
in Platform
.Modules
:
483 PlatformModule
= Platform
.Modules
[str(BuildData
.MetaFile
)]
484 if key
in PlatformModule
.Pcds
:
485 PcdInPlatform
= PlatformModule
.Pcds
[key
]
486 if PcdInPlatform
.Type
not in [None, '']:
487 BuildData
.Pcds
[key
].Type
= PcdInPlatform
.Type
489 if 'DynamicEx' in BuildData
.Pcds
[key
].Type
:
490 if BuildData
.IsBinaryModule
:
491 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) not in BinaryPcdDict
['DynamicEx']:
492 BinaryPcdDict
['DynamicEx'].append((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
494 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) not in SourcePcdDict
['DynamicEx']:
495 SourcePcdDict
['DynamicEx'].append((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
497 elif 'PatchableInModule' in BuildData
.Pcds
[key
].Type
:
498 if BuildData
.MetaFile
.Ext
== '.inf':
499 if BuildData
.IsBinaryModule
:
500 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) not in BinaryPcdDict
['PatchableInModule']:
501 BinaryPcdDict
['PatchableInModule'].append((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
503 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) not in SourcePcdDict
['PatchableInModule']:
504 SourcePcdDict
['PatchableInModule'].append((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
506 elif 'Dynamic' in BuildData
.Pcds
[key
].Type
:
507 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) not in SourcePcdDict
['Dynamic']:
508 SourcePcdDict
['Dynamic'].append((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
509 elif 'FixedAtBuild' in BuildData
.Pcds
[key
].Type
:
510 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) not in SourcePcdDict
['FixedAtBuild']:
511 SourcePcdDict
['FixedAtBuild'].append((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
515 # A PCD can only use one type for all source modules
517 for i
in SourcePcdDict_Keys
:
518 for j
in SourcePcdDict_Keys
:
520 IntersectionList
= list(set(SourcePcdDict
[i
]).intersection(set(SourcePcdDict
[j
])))
521 if len(IntersectionList
) > 0:
525 "Building modules from source INFs, following PCD use %s and %s access method. It must be corrected to use only one access method." % (i
, j
),
526 ExtraData
="%s" % '\n\t'.join([str(P
[1]+'.'+P
[0]) for P
in IntersectionList
])
532 # intersection the BinaryPCD for Mixed PCD
534 for i
in BinaryPcdDict_Keys
:
535 for j
in BinaryPcdDict_Keys
:
537 IntersectionList
= list(set(BinaryPcdDict
[i
]).intersection(set(BinaryPcdDict
[j
])))
538 for item
in IntersectionList
:
539 NewPcd1
= (item
[0] + '_' + i
, item
[1])
540 NewPcd2
= (item
[0] + '_' + j
, item
[1])
541 if item
not in GlobalData
.MixedPcd
:
542 GlobalData
.MixedPcd
[item
] = [NewPcd1
, NewPcd2
]
544 if NewPcd1
not in GlobalData
.MixedPcd
[item
]:
545 GlobalData
.MixedPcd
[item
].append(NewPcd1
)
546 if NewPcd2
not in GlobalData
.MixedPcd
[item
]:
547 GlobalData
.MixedPcd
[item
].append(NewPcd2
)
552 # intersection the SourcePCD and BinaryPCD for Mixed PCD
554 for i
in SourcePcdDict_Keys
:
555 for j
in BinaryPcdDict_Keys
:
557 IntersectionList
= list(set(SourcePcdDict
[i
]).intersection(set(BinaryPcdDict
[j
])))
558 for item
in IntersectionList
:
559 NewPcd1
= (item
[0] + '_' + i
, item
[1])
560 NewPcd2
= (item
[0] + '_' + j
, item
[1])
561 if item
not in GlobalData
.MixedPcd
:
562 GlobalData
.MixedPcd
[item
] = [NewPcd1
, NewPcd2
]
564 if NewPcd1
not in GlobalData
.MixedPcd
[item
]:
565 GlobalData
.MixedPcd
[item
].append(NewPcd1
)
566 if NewPcd2
not in GlobalData
.MixedPcd
[item
]:
567 GlobalData
.MixedPcd
[item
].append(NewPcd2
)
571 for BuildData
in PGen
.BuildDatabase
._CACHE
_.values():
572 if BuildData
.Arch
!= Arch
:
574 for key
in BuildData
.Pcds
:
575 for SinglePcd
in GlobalData
.MixedPcd
:
576 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) == SinglePcd
:
577 for item
in GlobalData
.MixedPcd
[SinglePcd
]:
578 Pcd_Type
= item
[0].split('_')[-1]
579 if (Pcd_Type
== BuildData
.Pcds
[key
].Type
) or (Pcd_Type
== TAB_PCDS_DYNAMIC_EX
and BuildData
.Pcds
[key
].Type
in GenC
.gDynamicExPcd
) or \
580 (Pcd_Type
== TAB_PCDS_DYNAMIC
and BuildData
.Pcds
[key
].Type
in GenC
.gDynamicPcd
):
581 Value
= BuildData
.Pcds
[key
]
582 Value
.TokenCName
= BuildData
.Pcds
[key
].TokenCName
+ '_' + Pcd_Type
584 newkey
= (Value
.TokenCName
, key
[1])
586 newkey
= (Value
.TokenCName
, key
[1], key
[2])
587 del BuildData
.Pcds
[key
]
588 BuildData
.Pcds
[newkey
] = Value
596 # handle the mixed pcd in FDF file
598 if key
in GlobalData
.MixedPcd
:
601 for item
in GlobalData
.MixedPcd
[key
]:
604 #Collect package set information from INF of FDF
606 for Inf
in ModuleList
:
607 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
608 if ModuleFile
in Platform
.Modules
:
610 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, Target
, Toolchain
]
611 PkgSet
.update(ModuleData
.Packages
)
612 Pkgs
= list(PkgSet
) + list(PGen
.PackageList
)
615 DecPcds
[Pcd
[0], Pcd
[1]] = Pkg
.Pcds
[Pcd
]
616 DecPcdsKey
.add((Pcd
[0], Pcd
[1], Pcd
[2]))
618 Platform
.SkuName
= self
.SkuId
619 for Name
, Guid
in PcdSet
:
620 if (Name
, Guid
) not in DecPcds
:
624 "PCD (%s.%s) used in FDF is not declared in DEC files." % (Guid
, Name
),
625 File
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][0],
626 Line
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][1]
629 # Check whether Dynamic or DynamicEx PCD used in FDF file. If used, build break and give a error message.
630 if (Name
, Guid
, TAB_PCDS_FIXED_AT_BUILD
) in DecPcdsKey \
631 or (Name
, Guid
, TAB_PCDS_PATCHABLE_IN_MODULE
) in DecPcdsKey \
632 or (Name
, Guid
, TAB_PCDS_FEATURE_FLAG
) in DecPcdsKey
:
633 Platform
.AddPcd(Name
, Guid
, PcdSet
[Name
, Guid
])
635 elif (Name
, Guid
, TAB_PCDS_DYNAMIC
) in DecPcdsKey
or (Name
, Guid
, TAB_PCDS_DYNAMIC_EX
) in DecPcdsKey
:
639 "Using Dynamic or DynamicEx type of PCD [%s.%s] in FDF file is not allowed." % (Guid
, Name
),
640 File
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][0],
641 Line
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][1]
644 Pa
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
646 # Explicitly collect platform's dynamic PCDs
648 Pa
.CollectPlatformDynamicPcds()
649 Pa
.CollectFixedAtBuildPcds()
650 self
.AutoGenObjectList
.append(Pa
)
653 # Generate Package level hash value
655 GlobalData
.gPackageHash
[Arch
] = {}
656 if GlobalData
.gUseHashCache
:
658 self
._GenPkgLevelHash
(Pkg
)
661 # Check PCDs token value conflict in each DEC file.
663 self
._CheckAllPcdsTokenValueConflict
()
666 # Check PCD type and definition between DSC and DEC
668 self
._CheckPcdDefineAndType
()
671 # self._CheckDuplicateInFV(Fdf)
674 # Create BuildOptions Macro & PCD metafile, also add the Active Platform and FDF file.
676 content
= 'gCommandLineDefines: '
677 content
+= str(GlobalData
.gCommandLineDefines
)
678 content
+= os
.linesep
679 content
+= 'BuildOptionPcd: '
680 content
+= str(GlobalData
.BuildOptionPcd
)
681 content
+= os
.linesep
682 content
+= 'Active Platform: '
683 content
+= str(self
.Platform
)
684 content
+= os
.linesep
686 content
+= 'Flash Image Definition: '
687 content
+= str(self
.FdfFile
)
688 content
+= os
.linesep
689 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'BuildOptions'), content
, False)
692 # Create PcdToken Number file for Dynamic/DynamicEx Pcd.
694 PcdTokenNumber
= 'PcdTokenNumber: '
695 if Pa
.PcdTokenNumber
:
696 if Pa
.DynamicPcdList
:
697 for Pcd
in Pa
.DynamicPcdList
:
698 PcdTokenNumber
+= os
.linesep
699 PcdTokenNumber
+= str((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
))
700 PcdTokenNumber
+= ' : '
701 PcdTokenNumber
+= str(Pa
.PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
])
702 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'PcdTokenNumber'), PcdTokenNumber
, False)
705 # Get set of workspace metafiles
707 AllWorkSpaceMetaFiles
= self
._GetMetaFiles
(Target
, Toolchain
, Arch
)
710 # Retrieve latest modified time of all metafiles
713 for f
in AllWorkSpaceMetaFiles
:
714 if os
.stat(f
)[8] > SrcTimeStamp
:
715 SrcTimeStamp
= os
.stat(f
)[8]
716 self
._SrcTimeStamp
= SrcTimeStamp
718 if GlobalData
.gUseHashCache
:
720 for files
in AllWorkSpaceMetaFiles
:
721 if files
.endswith('.dec'):
727 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'AutoGen.hash'), m
.hexdigest(), True)
728 GlobalData
.gPlatformHash
= m
.hexdigest()
731 # Write metafile list to build directory
733 AutoGenFilePath
= os
.path
.join(self
.BuildDir
, 'AutoGen')
734 if os
.path
.exists (AutoGenFilePath
):
735 os
.remove(AutoGenFilePath
)
736 if not os
.path
.exists(self
.BuildDir
):
737 os
.makedirs(self
.BuildDir
)
738 with
open(os
.path
.join(self
.BuildDir
, 'AutoGen'), 'w+') as file:
739 for f
in AllWorkSpaceMetaFiles
:
743 def _GenPkgLevelHash(self
, Pkg
):
744 PkgDir
= os
.path
.join(self
.BuildDir
, Pkg
.Arch
, Pkg
.PackageName
)
745 CreateDirectory(PkgDir
)
746 HashFile
= os
.path
.join(PkgDir
, Pkg
.PackageName
+ '.hash')
748 # Get .dec file's hash value
749 f
= open(Pkg
.MetaFile
.Path
, 'r')
753 # Get include files hash value
755 for inc
in Pkg
.Includes
:
756 for Root
, Dirs
, Files
in os
.walk(str(inc
)):
758 File_Path
= os
.path
.join(Root
, File
)
759 f
= open(File_Path
, 'r')
763 SaveFileOnChange(HashFile
, m
.hexdigest(), True)
764 if Pkg
.PackageName
not in GlobalData
.gPackageHash
[Pkg
.Arch
]:
765 GlobalData
.gPackageHash
[Pkg
.Arch
][Pkg
.PackageName
] = m
.hexdigest()
767 def _GetMetaFiles(self
, Target
, Toolchain
, Arch
):
768 AllWorkSpaceMetaFiles
= set()
773 AllWorkSpaceMetaFiles
.add (self
.FdfFile
.Path
)
775 FdfFiles
= GlobalData
.gFdfParser
.GetAllIncludedFile()
777 AllWorkSpaceMetaFiles
.add (f
.FileName
)
781 AllWorkSpaceMetaFiles
.add(self
.MetaFile
.Path
)
784 # add build_rule.txt & tools_def.txt
786 AllWorkSpaceMetaFiles
.add(os
.path
.join(GlobalData
.gConfDirectory
, gDefaultBuildRuleFile
))
787 AllWorkSpaceMetaFiles
.add(os
.path
.join(GlobalData
.gConfDirectory
, gDefaultToolsDefFile
))
789 # add BuildOption metafile
791 AllWorkSpaceMetaFiles
.add(os
.path
.join(self
.BuildDir
, 'BuildOptions'))
793 # add PcdToken Number file for Dynamic/DynamicEx Pcd
795 AllWorkSpaceMetaFiles
.add(os
.path
.join(self
.BuildDir
, 'PcdTokenNumber'))
797 for Arch
in self
.ArchList
:
798 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
799 PGen
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
804 for Package
in PGen
.PackageList
:
805 AllWorkSpaceMetaFiles
.add(Package
.MetaFile
.Path
)
810 for filePath
in Platform
._RawData
.IncludedFiles
:
811 AllWorkSpaceMetaFiles
.add(filePath
.Path
)
813 return AllWorkSpaceMetaFiles
815 ## _CheckDuplicateInFV() method
817 # Check whether there is duplicate modules/files exist in FV section.
818 # The check base on the file GUID;
820 def _CheckDuplicateInFV(self
, Fdf
):
821 for Fv
in Fdf
.Profile
.FvDict
:
823 for FfsFile
in Fdf
.Profile
.FvDict
[Fv
].FfsList
:
824 if FfsFile
.InfFileName
and FfsFile
.NameGuid
== None:
829 for Pa
in self
.AutoGenObjectList
:
832 for Module
in Pa
.ModuleAutoGenList
:
833 if path
.normpath(Module
.MetaFile
.File
) == path
.normpath(FfsFile
.InfFileName
):
835 if not Module
.Guid
.upper() in _GuidDict
.keys():
836 _GuidDict
[Module
.Guid
.upper()] = FfsFile
839 EdkLogger
.error("build",
841 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile
.CurrentLineNum
,
842 FfsFile
.CurrentLineContent
,
843 _GuidDict
[Module
.Guid
.upper()].CurrentLineNum
,
844 _GuidDict
[Module
.Guid
.upper()].CurrentLineContent
,
845 Module
.Guid
.upper()),
846 ExtraData
=self
.FdfFile
)
848 # Some INF files not have entity in DSC file.
851 if FfsFile
.InfFileName
.find('$') == -1:
852 InfPath
= NormPath(FfsFile
.InfFileName
)
853 if not os
.path
.exists(InfPath
):
854 EdkLogger
.error('build', GENFDS_ERROR
, "Non-existant Module %s !" % (FfsFile
.InfFileName
))
856 PathClassObj
= PathClass(FfsFile
.InfFileName
, self
.WorkspaceDir
)
858 # Here we just need to get FILE_GUID from INF file, use 'COMMON' as ARCH attribute. and use
859 # BuildObject from one of AutoGenObjectList is enough.
861 InfObj
= self
.AutoGenObjectList
[0].BuildDatabase
.WorkspaceDb
.BuildObject
[PathClassObj
, 'COMMON', self
.BuildTarget
, self
.ToolChain
]
862 if not InfObj
.Guid
.upper() in _GuidDict
.keys():
863 _GuidDict
[InfObj
.Guid
.upper()] = FfsFile
865 EdkLogger
.error("build",
867 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile
.CurrentLineNum
,
868 FfsFile
.CurrentLineContent
,
869 _GuidDict
[InfObj
.Guid
.upper()].CurrentLineNum
,
870 _GuidDict
[InfObj
.Guid
.upper()].CurrentLineContent
,
871 InfObj
.Guid
.upper()),
872 ExtraData
=self
.FdfFile
)
875 if FfsFile
.NameGuid
!= None:
876 _CheckPCDAsGuidPattern
= re
.compile("^PCD\(.+\..+\)$")
879 # If the NameGuid reference a PCD name.
880 # The style must match: PCD(xxxx.yyy)
882 if _CheckPCDAsGuidPattern
.match(FfsFile
.NameGuid
):
884 # Replace the PCD value.
886 _PcdName
= FfsFile
.NameGuid
.lstrip("PCD(").rstrip(")")
888 for Pa
in self
.AutoGenObjectList
:
890 for PcdItem
in Pa
.AllPcdList
:
891 if (PcdItem
.TokenSpaceGuidCName
+ "." + PcdItem
.TokenCName
) == _PcdName
:
893 # First convert from CFormatGuid to GUID string
895 _PcdGuidString
= GuidStructureStringToGuidString(PcdItem
.DefaultValue
)
897 if not _PcdGuidString
:
899 # Then try Byte array.
901 _PcdGuidString
= GuidStructureByteArrayToGuidString(PcdItem
.DefaultValue
)
903 if not _PcdGuidString
:
905 # Not Byte array or CFormat GUID, raise error.
907 EdkLogger
.error("build",
909 "The format of PCD value is incorrect. PCD: %s , Value: %s\n" % (_PcdName
, PcdItem
.DefaultValue
),
910 ExtraData
=self
.FdfFile
)
912 if not _PcdGuidString
.upper() in _GuidDict
.keys():
913 _GuidDict
[_PcdGuidString
.upper()] = FfsFile
917 EdkLogger
.error("build",
919 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile
.CurrentLineNum
,
920 FfsFile
.CurrentLineContent
,
921 _GuidDict
[_PcdGuidString
.upper()].CurrentLineNum
,
922 _GuidDict
[_PcdGuidString
.upper()].CurrentLineContent
,
923 FfsFile
.NameGuid
.upper()),
924 ExtraData
=self
.FdfFile
)
926 if not FfsFile
.NameGuid
.upper() in _GuidDict
.keys():
927 _GuidDict
[FfsFile
.NameGuid
.upper()] = FfsFile
930 # Two raw file GUID conflict.
932 EdkLogger
.error("build",
934 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile
.CurrentLineNum
,
935 FfsFile
.CurrentLineContent
,
936 _GuidDict
[FfsFile
.NameGuid
.upper()].CurrentLineNum
,
937 _GuidDict
[FfsFile
.NameGuid
.upper()].CurrentLineContent
,
938 FfsFile
.NameGuid
.upper()),
939 ExtraData
=self
.FdfFile
)
942 def _CheckPcdDefineAndType(self
):
944 "FixedAtBuild", "PatchableInModule", "FeatureFlag",
945 "Dynamic", #"DynamicHii", "DynamicVpd",
946 "DynamicEx", # "DynamicExHii", "DynamicExVpd"
949 # This dict store PCDs which are not used by any modules with specified arches
951 for Pa
in self
.AutoGenObjectList
:
952 # Key of DSC's Pcds dictionary is PcdCName, TokenSpaceGuid
953 for Pcd
in Pa
.Platform
.Pcds
:
954 PcdType
= Pa
.Platform
.Pcds
[Pcd
].Type
956 # If no PCD type, this PCD comes from FDF
960 # Try to remove Hii and Vpd suffix
961 if PcdType
.startswith("DynamicEx"):
962 PcdType
= "DynamicEx"
963 elif PcdType
.startswith("Dynamic"):
966 for Package
in Pa
.PackageList
:
967 # Key of DEC's Pcds dictionary is PcdCName, TokenSpaceGuid, PcdType
968 if (Pcd
[0], Pcd
[1], PcdType
) in Package
.Pcds
:
970 for Type
in PcdTypeList
:
971 if (Pcd
[0], Pcd
[1], Type
) in Package
.Pcds
:
975 "Type [%s] of PCD [%s.%s] in DSC file doesn't match the type [%s] defined in DEC file." \
976 % (Pa
.Platform
.Pcds
[Pcd
].Type
, Pcd
[1], Pcd
[0], Type
),
981 UnusedPcd
.setdefault(Pcd
, []).append(Pa
.Arch
)
983 for Pcd
in UnusedPcd
:
986 "The PCD was not specified by any INF module in the platform for the given architecture.\n"
987 "\tPCD: [%s.%s]\n\tPlatform: [%s]\n\tArch: %s"
988 % (Pcd
[1], Pcd
[0], os
.path
.basename(str(self
.MetaFile
)), str(UnusedPcd
[Pcd
])),
993 return "%s [%s]" % (self
.MetaFile
, ", ".join(self
.ArchList
))
995 ## Return the directory to store FV files
997 if self
._FvDir
== None:
998 self
._FvDir
= path
.join(self
.BuildDir
, 'FV')
1001 ## Return the directory to store all intermediate and final files built
1002 def _GetBuildDir(self
):
1003 if self
._BuildDir
== None:
1004 return self
.AutoGenObjectList
[0].BuildDir
1006 ## Return the build output directory platform specifies
1007 def _GetOutputDir(self
):
1008 return self
.Platform
.OutputDirectory
1010 ## Return platform name
1012 return self
.Platform
.PlatformName
1014 ## Return meta-file GUID
1016 return self
.Platform
.Guid
1018 ## Return platform version
1019 def _GetVersion(self
):
1020 return self
.Platform
.Version
1022 ## Return paths of tools
1023 def _GetToolDefinition(self
):
1024 return self
.AutoGenObjectList
[0].ToolDefinition
1026 ## Return directory of platform makefile
1028 # @retval string Makefile directory
1030 def _GetMakeFileDir(self
):
1031 if self
._MakeFileDir
== None:
1032 self
._MakeFileDir
= self
.BuildDir
1033 return self
._MakeFileDir
1035 ## Return build command string
1037 # @retval string Build command string
1039 def _GetBuildCommand(self
):
1040 if self
._BuildCommand
== None:
1041 # BuildCommand should be all the same. So just get one from platform AutoGen
1042 self
._BuildCommand
= self
.AutoGenObjectList
[0].BuildCommand
1043 return self
._BuildCommand
1045 ## Check the PCDs token value conflict in each DEC file.
1047 # Will cause build break and raise error message while two PCDs conflict.
1051 def _CheckAllPcdsTokenValueConflict(self
):
1052 for Pa
in self
.AutoGenObjectList
:
1053 for Package
in Pa
.PackageList
:
1054 PcdList
= Package
.Pcds
.values()
1055 PcdList
.sort(lambda x
, y
: cmp(int(x
.TokenValue
, 0), int(y
.TokenValue
, 0)))
1057 while (Count
< len(PcdList
) - 1) :
1058 Item
= PcdList
[Count
]
1059 ItemNext
= PcdList
[Count
+ 1]
1061 # Make sure in the same token space the TokenValue should be unique
1063 if (int(Item
.TokenValue
, 0) == int(ItemNext
.TokenValue
, 0)):
1064 SameTokenValuePcdList
= []
1065 SameTokenValuePcdList
.append(Item
)
1066 SameTokenValuePcdList
.append(ItemNext
)
1067 RemainPcdListLength
= len(PcdList
) - Count
- 2
1068 for ValueSameCount
in range(RemainPcdListLength
):
1069 if int(PcdList
[len(PcdList
) - RemainPcdListLength
+ ValueSameCount
].TokenValue
, 0) == int(Item
.TokenValue
, 0):
1070 SameTokenValuePcdList
.append(PcdList
[len(PcdList
) - RemainPcdListLength
+ ValueSameCount
])
1074 # Sort same token value PCD list with TokenGuid and TokenCName
1076 SameTokenValuePcdList
.sort(lambda x
, y
: cmp("%s.%s" % (x
.TokenSpaceGuidCName
, x
.TokenCName
), "%s.%s" % (y
.TokenSpaceGuidCName
, y
.TokenCName
)))
1077 SameTokenValuePcdListCount
= 0
1078 while (SameTokenValuePcdListCount
< len(SameTokenValuePcdList
) - 1):
1080 TemListItem
= SameTokenValuePcdList
[SameTokenValuePcdListCount
]
1081 TemListItemNext
= SameTokenValuePcdList
[SameTokenValuePcdListCount
+ 1]
1083 if (TemListItem
.TokenSpaceGuidCName
== TemListItemNext
.TokenSpaceGuidCName
) and (TemListItem
.TokenCName
!= TemListItemNext
.TokenCName
):
1084 for PcdItem
in GlobalData
.MixedPcd
:
1085 if (TemListItem
.TokenCName
, TemListItem
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
] or \
1086 (TemListItemNext
.TokenCName
, TemListItemNext
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
1092 "The TokenValue [%s] of PCD [%s.%s] is conflict with: [%s.%s] in %s"\
1093 % (TemListItem
.TokenValue
, TemListItem
.TokenSpaceGuidCName
, TemListItem
.TokenCName
, TemListItemNext
.TokenSpaceGuidCName
, TemListItemNext
.TokenCName
, Package
),
1096 SameTokenValuePcdListCount
+= 1
1097 Count
+= SameTokenValuePcdListCount
1100 PcdList
= Package
.Pcds
.values()
1101 PcdList
.sort(lambda x
, y
: cmp("%s.%s" % (x
.TokenSpaceGuidCName
, x
.TokenCName
), "%s.%s" % (y
.TokenSpaceGuidCName
, y
.TokenCName
)))
1103 while (Count
< len(PcdList
) - 1) :
1104 Item
= PcdList
[Count
]
1105 ItemNext
= PcdList
[Count
+ 1]
1107 # Check PCDs with same TokenSpaceGuidCName.TokenCName have same token value as well.
1109 if (Item
.TokenSpaceGuidCName
== ItemNext
.TokenSpaceGuidCName
) and (Item
.TokenCName
== ItemNext
.TokenCName
) and (int(Item
.TokenValue
, 0) != int(ItemNext
.TokenValue
, 0)):
1113 "The TokenValue [%s] of PCD [%s.%s] in %s defined in two places should be same as well."\
1114 % (Item
.TokenValue
, Item
.TokenSpaceGuidCName
, Item
.TokenCName
, Package
),
1118 ## Generate fds command
1119 def _GenFdsCommand(self
):
1120 return (GenMake
.TopLevelMakefile(self
)._TEMPLATE
_.Replace(GenMake
.TopLevelMakefile(self
)._TemplateDict
)).strip()
1122 ## Create makefile for the platform and modules in it
1124 # @param CreateDepsMakeFile Flag indicating if the makefile for
1125 # modules will be created as well
1127 def CreateMakeFile(self
, CreateDepsMakeFile
=False):
1128 if CreateDepsMakeFile
:
1129 for Pa
in self
.AutoGenObjectList
:
1130 Pa
.CreateMakeFile(CreateDepsMakeFile
)
1132 ## Create autogen code for platform and modules
1134 # Since there's no autogen code for platform, this method will do nothing
1135 # if CreateModuleCodeFile is set to False.
1137 # @param CreateDepsCodeFile Flag indicating if creating module's
1138 # autogen code file or not
1140 def CreateCodeFile(self
, CreateDepsCodeFile
=False):
1141 if not CreateDepsCodeFile
:
1143 for Pa
in self
.AutoGenObjectList
:
1144 Pa
.CreateCodeFile(CreateDepsCodeFile
)
1146 ## Create AsBuilt INF file the platform
1148 def CreateAsBuiltInf(self
):
1151 Name
= property(_GetName
)
1152 Guid
= property(_GetGuid
)
1153 Version
= property(_GetVersion
)
1154 OutputDir
= property(_GetOutputDir
)
1156 ToolDefinition
= property(_GetToolDefinition
) # toolcode : tool path
1158 BuildDir
= property(_GetBuildDir
)
1159 FvDir
= property(_GetFvDir
)
1160 MakeFileDir
= property(_GetMakeFileDir
)
1161 BuildCommand
= property(_GetBuildCommand
)
1162 GenFdsCommand
= property(_GenFdsCommand
)
1164 ## AutoGen class for platform
1166 # PlatformAutoGen class will process the original information in platform
1167 # file in order to generate makefile for platform.
1169 class PlatformAutoGen(AutoGen
):
1171 # Used to store all PCDs for both PEI and DXE phase, in order to generate
1172 # correct PCD database
1175 _NonDynaPcdList_
= []
1179 # The priority list while override build option
1181 PrioList
= {"0x11111" : 16, # TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE (Highest)
1182 "0x01111" : 15, # ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
1183 "0x10111" : 14, # TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE
1184 "0x00111" : 13, # ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE
1185 "0x11011" : 12, # TARGET_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
1186 "0x01011" : 11, # ******_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
1187 "0x10011" : 10, # TARGET_*********_****_COMMANDTYPE_ATTRIBUTE
1188 "0x00011" : 9, # ******_*********_****_COMMANDTYPE_ATTRIBUTE
1189 "0x11101" : 8, # TARGET_TOOLCHAIN_ARCH_***********_ATTRIBUTE
1190 "0x01101" : 7, # ******_TOOLCHAIN_ARCH_***********_ATTRIBUTE
1191 "0x10101" : 6, # TARGET_*********_ARCH_***********_ATTRIBUTE
1192 "0x00101" : 5, # ******_*********_ARCH_***********_ATTRIBUTE
1193 "0x11001" : 4, # TARGET_TOOLCHAIN_****_***********_ATTRIBUTE
1194 "0x01001" : 3, # ******_TOOLCHAIN_****_***********_ATTRIBUTE
1195 "0x10001" : 2, # TARGET_*********_****_***********_ATTRIBUTE
1196 "0x00001" : 1} # ******_*********_****_***********_ATTRIBUTE (Lowest)
1198 ## The real constructor of PlatformAutoGen
1200 # This method is not supposed to be called by users of PlatformAutoGen. It's
1201 # only used by factory method __new__() to do real initialization work for an
1202 # object of PlatformAutoGen
1204 # @param Workspace WorkspaceAutoGen object
1205 # @param PlatformFile Platform file (DSC file)
1206 # @param Target Build target (DEBUG, RELEASE)
1207 # @param Toolchain Name of tool chain
1208 # @param Arch arch of the platform supports
1210 def _Init(self
, Workspace
, PlatformFile
, Target
, Toolchain
, Arch
):
1211 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen platform [%s] [%s]" % (PlatformFile
, Arch
))
1212 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (PlatformFile
, Arch
, Toolchain
, Target
)
1214 self
.MetaFile
= PlatformFile
1215 self
.Workspace
= Workspace
1216 self
.WorkspaceDir
= Workspace
.WorkspaceDir
1217 self
.ToolChain
= Toolchain
1218 self
.BuildTarget
= Target
1220 self
.SourceDir
= PlatformFile
.SubDir
1221 self
.SourceOverrideDir
= None
1222 self
.FdTargetList
= self
.Workspace
.FdTargetList
1223 self
.FvTargetList
= self
.Workspace
.FvTargetList
1224 self
.AllPcdList
= []
1225 # get the original module/package/platform objects
1226 self
.BuildDatabase
= Workspace
.BuildDatabase
1228 # flag indicating if the makefile/C-code file has been created or not
1229 self
.IsMakeFileCreated
= False
1230 self
.IsCodeFileCreated
= False
1232 self
._Platform
= None
1235 self
._Version
= None
1237 self
._BuildRule
= None
1238 self
._SourceDir
= None
1239 self
._BuildDir
= None
1240 self
._OutputDir
= None
1242 self
._MakeFileDir
= None
1243 self
._FdfFile
= None
1245 self
._PcdTokenNumber
= None # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
1246 self
._DynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1247 self
._NonDynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1248 self
._NonDynamicPcdDict
= {}
1250 self
._ToolDefinitions
= None
1251 self
._ToolDefFile
= None # toolcode : tool path
1252 self
._ToolChainFamily
= None
1253 self
._BuildRuleFamily
= None
1254 self
._BuildOption
= None # toolcode : option
1255 self
._EdkBuildOption
= None # edktoolcode : option
1256 self
._EdkIIBuildOption
= None # edkiitoolcode : option
1257 self
._PackageList
= None
1258 self
._ModuleAutoGenList
= None
1259 self
._LibraryAutoGenList
= None
1260 self
._BuildCommand
= None
1261 self
._AsBuildInfList
= []
1262 self
._AsBuildModuleList
= []
1263 if GlobalData
.gFdfParser
!= None:
1264 self
._AsBuildInfList
= GlobalData
.gFdfParser
.Profile
.InfList
1265 for Inf
in self
._AsBuildInfList
:
1266 InfClass
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, self
.Arch
)
1267 M
= self
.BuildDatabase
[InfClass
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1268 if not M
.IsSupportedArch
:
1270 self
._AsBuildModuleList
.append(InfClass
)
1271 # get library/modules for build
1272 self
.LibraryBuildDirectoryList
= []
1273 self
.ModuleBuildDirectoryList
= []
1277 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
1279 ## Create autogen code for platform and modules
1281 # Since there's no autogen code for platform, this method will do nothing
1282 # if CreateModuleCodeFile is set to False.
1284 # @param CreateModuleCodeFile Flag indicating if creating module's
1285 # autogen code file or not
1287 def CreateCodeFile(self
, CreateModuleCodeFile
=False):
1288 # only module has code to be greated, so do nothing if CreateModuleCodeFile is False
1289 if self
.IsCodeFileCreated
or not CreateModuleCodeFile
:
1292 for Ma
in self
.ModuleAutoGenList
:
1293 Ma
.CreateCodeFile(True)
1295 # don't do this twice
1296 self
.IsCodeFileCreated
= True
1298 ## Generate Fds Command
1299 def _GenFdsCommand(self
):
1300 return self
.Workspace
.GenFdsCommand
1302 ## Create makefile for the platform and mdoules in it
1304 # @param CreateModuleMakeFile Flag indicating if the makefile for
1305 # modules will be created as well
1307 def CreateMakeFile(self
, CreateModuleMakeFile
=False, FfsCommand
= {}):
1308 if CreateModuleMakeFile
:
1309 for ModuleFile
in self
.Platform
.Modules
:
1310 Ma
= ModuleAutoGen(self
.Workspace
, ModuleFile
, self
.BuildTarget
,
1311 self
.ToolChain
, self
.Arch
, self
.MetaFile
)
1312 if (ModuleFile
.File
, self
.Arch
) in FfsCommand
:
1313 Ma
.CreateMakeFile(True, FfsCommand
[ModuleFile
.File
, self
.Arch
])
1315 Ma
.CreateMakeFile(True)
1316 #Ma.CreateAsBuiltInf()
1318 # no need to create makefile for the platform more than once
1319 if self
.IsMakeFileCreated
:
1322 # create library/module build dirs for platform
1323 Makefile
= GenMake
.PlatformMakefile(self
)
1324 self
.LibraryBuildDirectoryList
= Makefile
.GetLibraryBuildDirectoryList()
1325 self
.ModuleBuildDirectoryList
= Makefile
.GetModuleBuildDirectoryList()
1327 self
.IsMakeFileCreated
= True
1329 ## Deal with Shared FixedAtBuild Pcds
1331 def CollectFixedAtBuildPcds(self
):
1332 for LibAuto
in self
.LibraryAutoGenList
:
1333 FixedAtBuildPcds
= {}
1334 ShareFixedAtBuildPcdsSameValue
= {}
1335 for Module
in LibAuto
._ReferenceModules
:
1336 for Pcd
in Module
.FixedAtBuildPcds
+ LibAuto
.FixedAtBuildPcds
:
1337 key
= ".".join((Pcd
.TokenSpaceGuidCName
,Pcd
.TokenCName
))
1338 if key
not in FixedAtBuildPcds
:
1339 ShareFixedAtBuildPcdsSameValue
[key
] = True
1340 FixedAtBuildPcds
[key
] = Pcd
.DefaultValue
1342 if FixedAtBuildPcds
[key
] != Pcd
.DefaultValue
:
1343 ShareFixedAtBuildPcdsSameValue
[key
] = False
1344 for Pcd
in LibAuto
.FixedAtBuildPcds
:
1345 key
= ".".join((Pcd
.TokenSpaceGuidCName
,Pcd
.TokenCName
))
1346 if (Pcd
.TokenCName
,Pcd
.TokenSpaceGuidCName
) not in self
.NonDynamicPcdDict
:
1349 DscPcd
= self
.NonDynamicPcdDict
[(Pcd
.TokenCName
,Pcd
.TokenSpaceGuidCName
)]
1350 if DscPcd
.Type
!= "FixedAtBuild":
1352 if key
in ShareFixedAtBuildPcdsSameValue
and ShareFixedAtBuildPcdsSameValue
[key
]:
1353 LibAuto
.ConstPcd
[key
] = Pcd
.DefaultValue
1355 ## Collect dynamic PCDs
1357 # Gather dynamic PCDs list from each module and their settings from platform
1358 # This interface should be invoked explicitly when platform action is created.
1360 def CollectPlatformDynamicPcds(self
):
1361 # Override the platform Pcd's value by build option
1362 if GlobalData
.BuildOptionPcd
:
1363 for key
in self
.Platform
.Pcds
:
1364 PlatformPcd
= self
.Platform
.Pcds
[key
]
1365 for PcdItem
in GlobalData
.BuildOptionPcd
:
1366 if (PlatformPcd
.TokenSpaceGuidCName
, PlatformPcd
.TokenCName
) == (PcdItem
[0], PcdItem
[1]):
1367 PlatformPcd
.DefaultValue
= PcdItem
[2]
1368 if PlatformPcd
.SkuInfoList
:
1369 Sku
= PlatformPcd
.SkuInfoList
[PlatformPcd
.SkuInfoList
.keys()[0]]
1370 Sku
.DefaultValue
= PcdItem
[2]
1373 for key
in self
.Platform
.Pcds
:
1374 for SinglePcd
in GlobalData
.MixedPcd
:
1375 if (self
.Platform
.Pcds
[key
].TokenCName
, self
.Platform
.Pcds
[key
].TokenSpaceGuidCName
) == SinglePcd
:
1376 for item
in GlobalData
.MixedPcd
[SinglePcd
]:
1377 Pcd_Type
= item
[0].split('_')[-1]
1378 if (Pcd_Type
== self
.Platform
.Pcds
[key
].Type
) or (Pcd_Type
== TAB_PCDS_DYNAMIC_EX
and self
.Platform
.Pcds
[key
].Type
in GenC
.gDynamicExPcd
) or \
1379 (Pcd_Type
== TAB_PCDS_DYNAMIC
and self
.Platform
.Pcds
[key
].Type
in GenC
.gDynamicPcd
):
1380 Value
= self
.Platform
.Pcds
[key
]
1381 Value
.TokenCName
= self
.Platform
.Pcds
[key
].TokenCName
+ '_' + Pcd_Type
1383 newkey
= (Value
.TokenCName
, key
[1])
1385 newkey
= (Value
.TokenCName
, key
[1], key
[2])
1386 del self
.Platform
.Pcds
[key
]
1387 self
.Platform
.Pcds
[newkey
] = Value
1395 # for gathering error information
1396 NoDatumTypePcdList
= set()
1398 self
._GuidValue
= {}
1400 for InfName
in self
._AsBuildInfList
:
1401 InfName
= mws
.join(self
.WorkspaceDir
, InfName
)
1402 FdfModuleList
.append(os
.path
.normpath(InfName
))
1403 for F
in self
.Platform
.Modules
.keys():
1404 M
= ModuleAutoGen(self
.Workspace
, F
, self
.BuildTarget
, self
.ToolChain
, self
.Arch
, self
.MetaFile
)
1405 #GuidValue.update(M.Guids)
1407 self
.Platform
.Modules
[F
].M
= M
1409 for PcdFromModule
in M
.ModulePcdList
+ M
.LibraryPcdList
:
1410 # make sure that the "VOID*" kind of datum has MaxDatumSize set
1411 if PcdFromModule
.DatumType
== "VOID*" and PcdFromModule
.MaxDatumSize
in [None, '']:
1412 NoDatumTypePcdList
.add("%s.%s [%s]" % (PcdFromModule
.TokenSpaceGuidCName
, PcdFromModule
.TokenCName
, F
))
1414 # Check the PCD from Binary INF or Source INF
1415 if M
.IsBinaryModule
== True:
1416 PcdFromModule
.IsFromBinaryInf
= True
1418 # Check the PCD from DSC or not
1419 if (PcdFromModule
.TokenCName
, PcdFromModule
.TokenSpaceGuidCName
) in self
.Platform
.Pcds
.keys():
1420 PcdFromModule
.IsFromDsc
= True
1422 PcdFromModule
.IsFromDsc
= False
1423 if PcdFromModule
.Type
in GenC
.gDynamicPcd
or PcdFromModule
.Type
in GenC
.gDynamicExPcd
:
1424 if F
.Path
not in FdfModuleList
:
1425 # If one of the Source built modules listed in the DSC is not listed
1426 # in FDF modules, and the INF lists a PCD can only use the PcdsDynamic
1427 # access method (it is only listed in the DEC file that declares the
1428 # PCD as PcdsDynamic), then build tool will report warning message
1429 # notify the PI that they are attempting to build a module that must
1430 # be included in a flash image in order to be functional. These Dynamic
1431 # PCD will not be added into the Database unless it is used by other
1432 # modules that are included in the FDF file.
1433 if PcdFromModule
.Type
in GenC
.gDynamicPcd
and \
1434 PcdFromModule
.IsFromBinaryInf
== False:
1435 # Print warning message to let the developer make a determine.
1436 if PcdFromModule
not in PcdNotInDb
:
1437 PcdNotInDb
.append(PcdFromModule
)
1439 # If one of the Source built modules listed in the DSC is not listed in
1440 # FDF modules, and the INF lists a PCD can only use the PcdsDynamicEx
1441 # access method (it is only listed in the DEC file that declares the
1442 # PCD as PcdsDynamicEx), then DO NOT break the build; DO NOT add the
1443 # PCD to the Platform's PCD Database.
1444 if PcdFromModule
.Type
in GenC
.gDynamicExPcd
:
1445 if PcdFromModule
not in PcdNotInDb
:
1446 PcdNotInDb
.append(PcdFromModule
)
1449 # If a dynamic PCD used by a PEM module/PEI module & DXE module,
1450 # it should be stored in Pcd PEI database, If a dynamic only
1451 # used by DXE module, it should be stored in DXE PCD database.
1452 # The default Phase is DXE
1454 if M
.ModuleType
in ["PEIM", "PEI_CORE"]:
1455 PcdFromModule
.Phase
= "PEI"
1456 if PcdFromModule
not in self
._DynaPcdList
_:
1457 self
._DynaPcdList
_.append(PcdFromModule
)
1458 elif PcdFromModule
.Phase
== 'PEI':
1459 # overwrite any the same PCD existing, if Phase is PEI
1460 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1461 self
._DynaPcdList
_[Index
] = PcdFromModule
1462 elif PcdFromModule
not in self
._NonDynaPcdList
_:
1463 self
._NonDynaPcdList
_.append(PcdFromModule
)
1464 elif PcdFromModule
in self
._NonDynaPcdList
_ and PcdFromModule
.IsFromBinaryInf
== True:
1465 Index
= self
._NonDynaPcdList
_.index(PcdFromModule
)
1466 if self
._NonDynaPcdList
_[Index
].IsFromBinaryInf
== False:
1467 #The PCD from Binary INF will override the same one from source INF
1468 self
._NonDynaPcdList
_.remove (self
._NonDynaPcdList
_[Index
])
1469 PcdFromModule
.Pending
= False
1470 self
._NonDynaPcdList
_.append (PcdFromModule
)
1471 # Parse the DynamicEx PCD from the AsBuild INF module list of FDF.
1473 for ModuleInf
in self
.Platform
.Modules
.keys():
1474 DscModuleList
.append (os
.path
.normpath(ModuleInf
.Path
))
1475 # add the PCD from modules that listed in FDF but not in DSC to Database
1476 for InfName
in FdfModuleList
:
1477 if InfName
not in DscModuleList
:
1478 InfClass
= PathClass(InfName
)
1479 M
= self
.BuildDatabase
[InfClass
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1480 # If a module INF in FDF but not in current arch's DSC module list, it must be module (either binary or source)
1481 # for different Arch. PCDs in source module for different Arch is already added before, so skip the source module here.
1482 # For binary module, if in current arch, we need to list the PCDs into database.
1483 if not M
.IsSupportedArch
:
1485 # Override the module PCD setting by platform setting
1486 ModulePcdList
= self
.ApplyPcdSetting(M
, M
.Pcds
)
1487 for PcdFromModule
in ModulePcdList
:
1488 PcdFromModule
.IsFromBinaryInf
= True
1489 PcdFromModule
.IsFromDsc
= False
1490 # Only allow the DynamicEx and Patchable PCD in AsBuild INF
1491 if PcdFromModule
.Type
not in GenC
.gDynamicExPcd
and PcdFromModule
.Type
not in TAB_PCDS_PATCHABLE_IN_MODULE
:
1492 EdkLogger
.error("build", AUTOGEN_ERROR
, "PCD setting error",
1494 ExtraData
="\n\tExisted %s PCD %s in:\n\t\t%s\n"
1495 % (PcdFromModule
.Type
, PcdFromModule
.TokenCName
, InfName
))
1496 # make sure that the "VOID*" kind of datum has MaxDatumSize set
1497 if PcdFromModule
.DatumType
== "VOID*" and PcdFromModule
.MaxDatumSize
in [None, '']:
1498 NoDatumTypePcdList
.add("%s.%s [%s]" % (PcdFromModule
.TokenSpaceGuidCName
, PcdFromModule
.TokenCName
, InfName
))
1499 if M
.ModuleType
in ["PEIM", "PEI_CORE"]:
1500 PcdFromModule
.Phase
= "PEI"
1501 if PcdFromModule
not in self
._DynaPcdList
_ and PcdFromModule
.Type
in GenC
.gDynamicExPcd
:
1502 self
._DynaPcdList
_.append(PcdFromModule
)
1503 elif PcdFromModule
not in self
._NonDynaPcdList
_ and PcdFromModule
.Type
in TAB_PCDS_PATCHABLE_IN_MODULE
:
1504 self
._NonDynaPcdList
_.append(PcdFromModule
)
1505 if PcdFromModule
in self
._DynaPcdList
_ and PcdFromModule
.Phase
== 'PEI' and PcdFromModule
.Type
in GenC
.gDynamicExPcd
:
1506 # Overwrite the phase of any the same PCD existing, if Phase is PEI.
1507 # It is to solve the case that a dynamic PCD used by a PEM module/PEI
1508 # module & DXE module at a same time.
1509 # Overwrite the type of the PCDs in source INF by the type of AsBuild
1510 # INF file as DynamicEx.
1511 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1512 self
._DynaPcdList
_[Index
].Phase
= PcdFromModule
.Phase
1513 self
._DynaPcdList
_[Index
].Type
= PcdFromModule
.Type
1514 for PcdFromModule
in self
._NonDynaPcdList
_:
1515 # If a PCD is not listed in the DSC file, but binary INF files used by
1516 # this platform all (that use this PCD) list the PCD in a [PatchPcds]
1517 # section, AND all source INF files used by this platform the build
1518 # that use the PCD list the PCD in either a [Pcds] or [PatchPcds]
1519 # section, then the tools must NOT add the PCD to the Platform's PCD
1520 # Database; the build must assign the access method for this PCD as
1521 # PcdsPatchableInModule.
1522 if PcdFromModule
not in self
._DynaPcdList
_:
1524 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1525 if PcdFromModule
.IsFromDsc
== False and \
1526 PcdFromModule
.Type
in TAB_PCDS_PATCHABLE_IN_MODULE
and \
1527 PcdFromModule
.IsFromBinaryInf
== True and \
1528 self
._DynaPcdList
_[Index
].IsFromBinaryInf
== False:
1529 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1530 self
._DynaPcdList
_.remove (self
._DynaPcdList
_[Index
])
1532 # print out error information and break the build, if error found
1533 if len(NoDatumTypePcdList
) > 0:
1534 NoDatumTypePcdListString
= "\n\t\t".join(NoDatumTypePcdList
)
1535 EdkLogger
.error("build", AUTOGEN_ERROR
, "PCD setting error",
1537 ExtraData
="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"
1538 % NoDatumTypePcdListString
)
1539 self
._NonDynamicPcdList
= self
._NonDynaPcdList
_
1540 self
._DynamicPcdList
= self
._DynaPcdList
_
1542 # Sort dynamic PCD list to:
1543 # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should
1544 # try to be put header of dynamicd List
1545 # 2) If PCD is HII type, the PCD item should be put after unicode type PCD
1547 # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.
1549 UnicodePcdArray
= []
1553 VpdFile
= VpdInfoFile
.VpdInfoFile()
1554 NeedProcessVpdMapFile
= False
1556 for pcd
in self
.Platform
.Pcds
.keys():
1557 if pcd
not in self
._PlatformPcds
.keys():
1558 self
._PlatformPcds
[pcd
] = self
.Platform
.Pcds
[pcd
]
1560 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 GlobalData
.gBuildDirectory
= self
._BuildDir
1802 return self
._BuildDir
1804 ## Return directory of platform makefile
1806 # @retval string Makefile directory
1808 def _GetMakeFileDir(self
):
1809 if self
._MakeFileDir
== None:
1810 self
._MakeFileDir
= path
.join(self
.BuildDir
, self
.Arch
)
1811 return self
._MakeFileDir
1813 ## Return build command string
1815 # @retval string Build command string
1817 def _GetBuildCommand(self
):
1818 if self
._BuildCommand
== None:
1819 self
._BuildCommand
= []
1820 if "MAKE" in self
.ToolDefinition
and "PATH" in self
.ToolDefinition
["MAKE"]:
1821 self
._BuildCommand
+= SplitOption(self
.ToolDefinition
["MAKE"]["PATH"])
1822 if "FLAGS" in self
.ToolDefinition
["MAKE"]:
1823 NewOption
= self
.ToolDefinition
["MAKE"]["FLAGS"].strip()
1825 self
._BuildCommand
+= SplitOption(NewOption
)
1826 return self
._BuildCommand
1828 ## Get tool chain definition
1830 # Get each tool defition for given tool chain from tools_def.txt and platform
1832 def _GetToolDefinition(self
):
1833 if self
._ToolDefinitions
== None:
1834 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDictionary
1835 if TAB_TOD_DEFINES_COMMAND_TYPE
not in self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
:
1836 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
, "No tools found in configuration",
1837 ExtraData
="[%s]" % self
.MetaFile
)
1838 self
._ToolDefinitions
= {}
1840 for Def
in ToolDefinition
:
1841 Target
, Tag
, Arch
, Tool
, Attr
= Def
.split("_")
1842 if Target
!= self
.BuildTarget
or Tag
!= self
.ToolChain
or Arch
!= self
.Arch
:
1845 Value
= ToolDefinition
[Def
]
1846 # don't record the DLL
1848 DllPathList
.add(Value
)
1851 if Tool
not in self
._ToolDefinitions
:
1852 self
._ToolDefinitions
[Tool
] = {}
1853 self
._ToolDefinitions
[Tool
][Attr
] = Value
1857 if GlobalData
.gOptions
.SilentMode
and "MAKE" in self
._ToolDefinitions
:
1858 if "FLAGS" not in self
._ToolDefinitions
["MAKE"]:
1859 self
._ToolDefinitions
["MAKE"]["FLAGS"] = ""
1860 self
._ToolDefinitions
["MAKE"]["FLAGS"] += " -s"
1862 for Tool
in self
._ToolDefinitions
:
1863 for Attr
in self
._ToolDefinitions
[Tool
]:
1864 Value
= self
._ToolDefinitions
[Tool
][Attr
]
1865 if Tool
in self
.BuildOption
and Attr
in self
.BuildOption
[Tool
]:
1866 # check if override is indicated
1867 if self
.BuildOption
[Tool
][Attr
].startswith('='):
1868 Value
= self
.BuildOption
[Tool
][Attr
][1:]
1871 Value
+= " " + self
.BuildOption
[Tool
][Attr
]
1873 Value
= self
.BuildOption
[Tool
][Attr
]
1876 # Don't put MAKE definition in the file
1880 ToolsDef
+= "%s = %s\n" % (Tool
, Value
)
1882 # Don't put MAKE definition in the file
1887 ToolsDef
+= "%s_%s = %s\n" % (Tool
, Attr
, Value
)
1890 SaveFileOnChange(self
.ToolDefinitionFile
, ToolsDef
)
1891 for DllPath
in DllPathList
:
1892 os
.environ
["PATH"] = DllPath
+ os
.pathsep
+ os
.environ
["PATH"]
1893 os
.environ
["MAKE_FLAGS"] = MakeFlags
1895 return self
._ToolDefinitions
1897 ## Return the paths of tools
1898 def _GetToolDefFile(self
):
1899 if self
._ToolDefFile
== None:
1900 self
._ToolDefFile
= os
.path
.join(self
.MakeFileDir
, "TOOLS_DEF." + self
.Arch
)
1901 return self
._ToolDefFile
1903 ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
1904 def _GetToolChainFamily(self
):
1905 if self
._ToolChainFamily
== None:
1906 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
1907 if TAB_TOD_DEFINES_FAMILY
not in ToolDefinition \
1908 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_FAMILY
] \
1909 or not ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]:
1910 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1912 self
._ToolChainFamily
= "MSFT"
1914 self
._ToolChainFamily
= ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]
1915 return self
._ToolChainFamily
1917 def _GetBuildRuleFamily(self
):
1918 if self
._BuildRuleFamily
== None:
1919 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
1920 if TAB_TOD_DEFINES_BUILDRULEFAMILY
not in ToolDefinition \
1921 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
] \
1922 or not ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]:
1923 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1925 self
._BuildRuleFamily
= "MSFT"
1927 self
._BuildRuleFamily
= ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]
1928 return self
._BuildRuleFamily
1930 ## Return the build options specific for all modules in this platform
1931 def _GetBuildOptions(self
):
1932 if self
._BuildOption
== None:
1933 self
._BuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
)
1934 return self
._BuildOption
1936 ## Return the build options specific for EDK modules in this platform
1937 def _GetEdkBuildOptions(self
):
1938 if self
._EdkBuildOption
== None:
1939 self
._EdkBuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDK_NAME
)
1940 return self
._EdkBuildOption
1942 ## Return the build options specific for EDKII modules in this platform
1943 def _GetEdkIIBuildOptions(self
):
1944 if self
._EdkIIBuildOption
== None:
1945 self
._EdkIIBuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDKII_NAME
)
1946 return self
._EdkIIBuildOption
1948 ## Parse build_rule.txt in Conf Directory.
1950 # @retval BuildRule object
1952 def _GetBuildRule(self
):
1953 if self
._BuildRule
== None:
1954 BuildRuleFile
= None
1955 if TAB_TAT_DEFINES_BUILD_RULE_CONF
in self
.Workspace
.TargetTxt
.TargetTxtDictionary
:
1956 BuildRuleFile
= self
.Workspace
.TargetTxt
.TargetTxtDictionary
[TAB_TAT_DEFINES_BUILD_RULE_CONF
]
1957 if BuildRuleFile
in [None, '']:
1958 BuildRuleFile
= gDefaultBuildRuleFile
1959 self
._BuildRule
= BuildRule(BuildRuleFile
)
1960 if self
._BuildRule
._FileVersion
== "":
1961 self
._BuildRule
._FileVersion
= AutoGenReqBuildRuleVerNum
1963 if self
._BuildRule
._FileVersion
< AutoGenReqBuildRuleVerNum
:
1964 # If Build Rule's version is less than the version number required by the tools, halting the build.
1965 EdkLogger
.error("build", AUTOGEN_ERROR
,
1966 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])"\
1967 % (self
._BuildRule
._FileVersion
, AutoGenReqBuildRuleVerNum
))
1969 return self
._BuildRule
1971 ## Summarize the packages used by modules in this platform
1972 def _GetPackageList(self
):
1973 if self
._PackageList
== None:
1974 self
._PackageList
= set()
1975 for La
in self
.LibraryAutoGenList
:
1976 self
._PackageList
.update(La
.DependentPackageList
)
1977 for Ma
in self
.ModuleAutoGenList
:
1978 self
._PackageList
.update(Ma
.DependentPackageList
)
1979 #Collect package set information from INF of FDF
1981 for ModuleFile
in self
._AsBuildModuleList
:
1982 if ModuleFile
in self
.Platform
.Modules
:
1984 ModuleData
= self
.BuildDatabase
[ModuleFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1985 PkgSet
.update(ModuleData
.Packages
)
1986 self
._PackageList
= list(self
._PackageList
) + list (PkgSet
)
1987 return self
._PackageList
1989 def _GetNonDynamicPcdDict(self
):
1990 if self
._NonDynamicPcdDict
:
1991 return self
._NonDynamicPcdDict
1992 for Pcd
in self
.NonDynamicPcdList
:
1993 self
._NonDynamicPcdDict
[(Pcd
.TokenCName
,Pcd
.TokenSpaceGuidCName
)] = Pcd
1994 return self
._NonDynamicPcdDict
1996 ## Get list of non-dynamic PCDs
1997 def _GetNonDynamicPcdList(self
):
1998 if self
._NonDynamicPcdList
== None:
1999 self
.CollectPlatformDynamicPcds()
2000 return self
._NonDynamicPcdList
2002 ## Get list of dynamic PCDs
2003 def _GetDynamicPcdList(self
):
2004 if self
._DynamicPcdList
== None:
2005 self
.CollectPlatformDynamicPcds()
2006 return self
._DynamicPcdList
2008 ## Generate Token Number for all PCD
2009 def _GetPcdTokenNumbers(self
):
2010 if self
._PcdTokenNumber
== None:
2011 self
._PcdTokenNumber
= sdict()
2014 # Make the Dynamic and DynamicEx PCD use within different TokenNumber area.
2018 # TokenNumber 0 ~ 10
2020 # TokeNumber 11 ~ 20
2022 for Pcd
in self
.DynamicPcdList
:
2023 if Pcd
.Phase
== "PEI":
2024 if Pcd
.Type
in ["Dynamic", "DynamicDefault", "DynamicVpd", "DynamicHii"]:
2025 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2026 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2029 for Pcd
in self
.DynamicPcdList
:
2030 if Pcd
.Phase
== "PEI":
2031 if Pcd
.Type
in ["DynamicEx", "DynamicExDefault", "DynamicExVpd", "DynamicExHii"]:
2032 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2033 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2036 for Pcd
in self
.DynamicPcdList
:
2037 if Pcd
.Phase
== "DXE":
2038 if Pcd
.Type
in ["Dynamic", "DynamicDefault", "DynamicVpd", "DynamicHii"]:
2039 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2040 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2043 for Pcd
in self
.DynamicPcdList
:
2044 if Pcd
.Phase
== "DXE":
2045 if Pcd
.Type
in ["DynamicEx", "DynamicExDefault", "DynamicExVpd", "DynamicExHii"]:
2046 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2047 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2050 for Pcd
in self
.NonDynamicPcdList
:
2051 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2053 return self
._PcdTokenNumber
2055 ## Summarize ModuleAutoGen objects of all modules/libraries to be built for this platform
2056 def _GetAutoGenObjectList(self
):
2057 self
._ModuleAutoGenList
= []
2058 self
._LibraryAutoGenList
= []
2059 for ModuleFile
in self
.Platform
.Modules
:
2068 if Ma
not in self
._ModuleAutoGenList
:
2069 self
._ModuleAutoGenList
.append(Ma
)
2070 for La
in Ma
.LibraryAutoGenList
:
2071 if La
not in self
._LibraryAutoGenList
:
2072 self
._LibraryAutoGenList
.append(La
)
2073 if Ma
not in La
._ReferenceModules
:
2074 La
._ReferenceModules
.append(Ma
)
2076 ## Summarize ModuleAutoGen objects of all modules to be built for this platform
2077 def _GetModuleAutoGenList(self
):
2078 if self
._ModuleAutoGenList
== None:
2079 self
._GetAutoGenObjectList
()
2080 return self
._ModuleAutoGenList
2082 ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
2083 def _GetLibraryAutoGenList(self
):
2084 if self
._LibraryAutoGenList
== None:
2085 self
._GetAutoGenObjectList
()
2086 return self
._LibraryAutoGenList
2088 ## Test if a module is supported by the platform
2090 # An error will be raised directly if the module or its arch is not supported
2091 # by the platform or current configuration
2093 def ValidModule(self
, Module
):
2094 return Module
in self
.Platform
.Modules
or Module
in self
.Platform
.LibraryInstances \
2095 or Module
in self
._AsBuildModuleList
2097 ## Resolve the library classes in a module to library instances
2099 # This method will not only resolve library classes but also sort the library
2100 # instances according to the dependency-ship.
2102 # @param Module The module from which the library classes will be resolved
2104 # @retval library_list List of library instances sorted
2106 def ApplyLibraryInstance(self
, Module
):
2107 # Cover the case that the binary INF file is list in the FDF file but not DSC file, return empty list directly
2108 if str(Module
) not in self
.Platform
.Modules
:
2111 ModuleType
= Module
.ModuleType
2113 # for overridding library instances with module specific setting
2114 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
2116 # add forced library instances (specified under LibraryClasses sections)
2118 # If a module has a MODULE_TYPE of USER_DEFINED,
2119 # do not link in NULL library class instances from the global [LibraryClasses.*] sections.
2121 if Module
.ModuleType
!= SUP_MODULE_USER_DEFINED
:
2122 for LibraryClass
in self
.Platform
.LibraryClasses
.GetKeys():
2123 if LibraryClass
.startswith("NULL") and self
.Platform
.LibraryClasses
[LibraryClass
, Module
.ModuleType
]:
2124 Module
.LibraryClasses
[LibraryClass
] = self
.Platform
.LibraryClasses
[LibraryClass
, Module
.ModuleType
]
2126 # add forced library instances (specified in module overrides)
2127 for LibraryClass
in PlatformModule
.LibraryClasses
:
2128 if LibraryClass
.startswith("NULL"):
2129 Module
.LibraryClasses
[LibraryClass
] = PlatformModule
.LibraryClasses
[LibraryClass
]
2132 LibraryConsumerList
= [Module
]
2134 ConsumedByList
= sdict()
2135 LibraryInstance
= sdict()
2137 EdkLogger
.verbose("")
2138 EdkLogger
.verbose("Library instances of module [%s] [%s]:" % (str(Module
), self
.Arch
))
2139 while len(LibraryConsumerList
) > 0:
2140 M
= LibraryConsumerList
.pop()
2141 for LibraryClassName
in M
.LibraryClasses
:
2142 if LibraryClassName
not in LibraryInstance
:
2143 # override library instance for this module
2144 if LibraryClassName
in PlatformModule
.LibraryClasses
:
2145 LibraryPath
= PlatformModule
.LibraryClasses
[LibraryClassName
]
2147 LibraryPath
= self
.Platform
.LibraryClasses
[LibraryClassName
, ModuleType
]
2148 if LibraryPath
== None or LibraryPath
== "":
2149 LibraryPath
= M
.LibraryClasses
[LibraryClassName
]
2150 if LibraryPath
== None or LibraryPath
== "":
2151 EdkLogger
.error("build", RESOURCE_NOT_AVAILABLE
,
2152 "Instance of library class [%s] is not found" % LibraryClassName
,
2154 ExtraData
="in [%s] [%s]\n\tconsumed by module [%s]" % (str(M
), self
.Arch
, str(Module
)))
2156 LibraryModule
= self
.BuildDatabase
[LibraryPath
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
2157 # for those forced library instance (NULL library), add a fake library class
2158 if LibraryClassName
.startswith("NULL"):
2159 LibraryModule
.LibraryClass
.append(LibraryClassObject(LibraryClassName
, [ModuleType
]))
2160 elif LibraryModule
.LibraryClass
== None \
2161 or len(LibraryModule
.LibraryClass
) == 0 \
2162 or (ModuleType
!= 'USER_DEFINED'
2163 and ModuleType
not in LibraryModule
.LibraryClass
[0].SupModList
):
2164 # only USER_DEFINED can link against any library instance despite of its SupModList
2165 EdkLogger
.error("build", OPTION_MISSING
,
2166 "Module type [%s] is not supported by library instance [%s]" \
2167 % (ModuleType
, LibraryPath
), File
=self
.MetaFile
,
2168 ExtraData
="consumed by [%s]" % str(Module
))
2170 LibraryInstance
[LibraryClassName
] = LibraryModule
2171 LibraryConsumerList
.append(LibraryModule
)
2172 EdkLogger
.verbose("\t" + str(LibraryClassName
) + " : " + str(LibraryModule
))
2174 LibraryModule
= LibraryInstance
[LibraryClassName
]
2176 if LibraryModule
== None:
2179 if LibraryModule
.ConstructorList
!= [] and LibraryModule
not in Constructor
:
2180 Constructor
.append(LibraryModule
)
2182 if LibraryModule
not in ConsumedByList
:
2183 ConsumedByList
[LibraryModule
] = []
2184 # don't add current module itself to consumer list
2186 if M
in ConsumedByList
[LibraryModule
]:
2188 ConsumedByList
[LibraryModule
].append(M
)
2190 # Initialize the sorted output list to the empty set
2192 SortedLibraryList
= []
2194 # Q <- Set of all nodes with no incoming edges
2196 LibraryList
= [] #LibraryInstance.values()
2198 for LibraryClassName
in LibraryInstance
:
2199 M
= LibraryInstance
[LibraryClassName
]
2200 LibraryList
.append(M
)
2201 if ConsumedByList
[M
] == []:
2205 # start the DAG algorithm
2209 while Q
== [] and EdgeRemoved
:
2211 # for each node Item with a Constructor
2212 for Item
in LibraryList
:
2213 if Item
not in Constructor
:
2215 # for each Node without a constructor with an edge e from Item to Node
2216 for Node
in ConsumedByList
[Item
]:
2217 if Node
in Constructor
:
2219 # remove edge e from the graph if Node has no constructor
2220 ConsumedByList
[Item
].remove(Node
)
2222 if ConsumedByList
[Item
] == []:
2223 # insert Item into Q
2228 # DAG is done if there's no more incoming edge for all nodes
2232 # remove node from Q
2235 SortedLibraryList
.append(Node
)
2237 # for each node Item with an edge e from Node to Item do
2238 for Item
in LibraryList
:
2239 if Node
not in ConsumedByList
[Item
]:
2241 # remove edge e from the graph
2242 ConsumedByList
[Item
].remove(Node
)
2244 if ConsumedByList
[Item
] != []:
2246 # insert Item into Q, if Item has no other incoming edges
2250 # if any remaining node Item in the graph has a constructor and an incoming edge, then the graph has a cycle
2252 for Item
in LibraryList
:
2253 if ConsumedByList
[Item
] != [] and Item
in Constructor
and len(Constructor
) > 1:
2254 ErrorMessage
= "\tconsumed by " + "\n\tconsumed by ".join([str(L
) for L
in ConsumedByList
[Item
]])
2255 EdkLogger
.error("build", BUILD_ERROR
, 'Library [%s] with constructors has a cycle' % str(Item
),
2256 ExtraData
=ErrorMessage
, File
=self
.MetaFile
)
2257 if Item
not in SortedLibraryList
:
2258 SortedLibraryList
.append(Item
)
2261 # Build the list of constructor and destructir names
2262 # The DAG Topo sort produces the destructor order, so the list of constructors must generated in the reverse order
2264 SortedLibraryList
.reverse()
2265 return SortedLibraryList
2268 ## Override PCD setting (type, value, ...)
2270 # @param ToPcd The PCD to be overrided
2271 # @param FromPcd The PCD overrideing from
2273 def _OverridePcd(self
, ToPcd
, FromPcd
, Module
=""):
2275 # in case there's PCDs coming from FDF file, which have no type given.
2276 # at this point, ToPcd.Type has the type found from dependent
2279 TokenCName
= ToPcd
.TokenCName
2280 for PcdItem
in GlobalData
.MixedPcd
:
2281 if (ToPcd
.TokenCName
, ToPcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
2282 TokenCName
= PcdItem
[0]
2285 if GlobalData
.BuildOptionPcd
:
2286 for pcd
in GlobalData
.BuildOptionPcd
:
2287 if (FromPcd
.TokenSpaceGuidCName
, FromPcd
.TokenCName
) == (pcd
[0], pcd
[1]):
2288 FromPcd
.DefaultValue
= pcd
[2]
2290 if ToPcd
.Pending
and FromPcd
.Type
not in [None, '']:
2291 ToPcd
.Type
= FromPcd
.Type
2292 elif (ToPcd
.Type
not in [None, '']) and (FromPcd
.Type
not in [None, ''])\
2293 and (ToPcd
.Type
!= FromPcd
.Type
) and (ToPcd
.Type
in FromPcd
.Type
):
2294 if ToPcd
.Type
.strip() == "DynamicEx":
2295 ToPcd
.Type
= FromPcd
.Type
2296 elif ToPcd
.Type
not in [None, ''] and FromPcd
.Type
not in [None, ''] \
2297 and ToPcd
.Type
!= FromPcd
.Type
:
2298 EdkLogger
.error("build", OPTION_CONFLICT
, "Mismatched PCD type",
2299 ExtraData
="%s.%s is defined as [%s] in module %s, but as [%s] in platform."\
2300 % (ToPcd
.TokenSpaceGuidCName
, TokenCName
,
2301 ToPcd
.Type
, Module
, FromPcd
.Type
),
2304 if FromPcd
.MaxDatumSize
not in [None, '']:
2305 ToPcd
.MaxDatumSize
= FromPcd
.MaxDatumSize
2306 if FromPcd
.DefaultValue
not in [None, '']:
2307 ToPcd
.DefaultValue
= FromPcd
.DefaultValue
2308 if FromPcd
.TokenValue
not in [None, '']:
2309 ToPcd
.TokenValue
= FromPcd
.TokenValue
2310 if FromPcd
.MaxDatumSize
not in [None, '']:
2311 ToPcd
.MaxDatumSize
= FromPcd
.MaxDatumSize
2312 if FromPcd
.DatumType
not in [None, '']:
2313 ToPcd
.DatumType
= FromPcd
.DatumType
2314 if FromPcd
.SkuInfoList
not in [None, '', []]:
2315 ToPcd
.SkuInfoList
= FromPcd
.SkuInfoList
2317 # check the validation of datum
2318 IsValid
, Cause
= CheckPcdDatum(ToPcd
.DatumType
, ToPcd
.DefaultValue
)
2320 EdkLogger
.error('build', FORMAT_INVALID
, Cause
, File
=self
.MetaFile
,
2321 ExtraData
="%s.%s" % (ToPcd
.TokenSpaceGuidCName
, TokenCName
))
2322 ToPcd
.validateranges
= FromPcd
.validateranges
2323 ToPcd
.validlists
= FromPcd
.validlists
2324 ToPcd
.expressions
= FromPcd
.expressions
2326 if ToPcd
.DatumType
== "VOID*" and ToPcd
.MaxDatumSize
in ['', None]:
2327 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "No MaxDatumSize specified for PCD %s.%s" \
2328 % (ToPcd
.TokenSpaceGuidCName
, TokenCName
))
2329 Value
= ToPcd
.DefaultValue
2330 if Value
in [None, '']:
2331 ToPcd
.MaxDatumSize
= '1'
2332 elif Value
[0] == 'L':
2333 ToPcd
.MaxDatumSize
= str((len(Value
) - 2) * 2)
2334 elif Value
[0] == '{':
2335 ToPcd
.MaxDatumSize
= str(len(Value
.split(',')))
2337 ToPcd
.MaxDatumSize
= str(len(Value
) - 1)
2339 # apply default SKU for dynamic PCDS if specified one is not available
2340 if (ToPcd
.Type
in PCD_DYNAMIC_TYPE_LIST
or ToPcd
.Type
in PCD_DYNAMIC_EX_TYPE_LIST
) \
2341 and ToPcd
.SkuInfoList
in [None, {}, '']:
2342 if self
.Platform
.SkuName
in self
.Platform
.SkuIds
:
2343 SkuName
= self
.Platform
.SkuName
2346 ToPcd
.SkuInfoList
= {
2347 SkuName
: SkuInfoClass(SkuName
, self
.Platform
.SkuIds
[SkuName
], '', '', '', '', '', ToPcd
.DefaultValue
)
2350 ## Apply PCD setting defined platform to a module
2352 # @param Module The module from which the PCD setting will be overrided
2354 # @retval PCD_list The list PCDs with settings from platform
2356 def ApplyPcdSetting(self
, Module
, Pcds
):
2357 # for each PCD in module
2358 for Name
, Guid
in Pcds
:
2359 PcdInModule
= Pcds
[Name
, Guid
]
2360 # find out the PCD setting in platform
2361 if (Name
, Guid
) in self
.Platform
.Pcds
:
2362 PcdInPlatform
= self
.Platform
.Pcds
[Name
, Guid
]
2364 PcdInPlatform
= None
2365 # then override the settings if any
2366 self
._OverridePcd
(PcdInModule
, PcdInPlatform
, Module
)
2367 # resolve the VariableGuid value
2368 for SkuId
in PcdInModule
.SkuInfoList
:
2369 Sku
= PcdInModule
.SkuInfoList
[SkuId
]
2370 if Sku
.VariableGuid
== '': continue
2371 Sku
.VariableGuidValue
= GuidValue(Sku
.VariableGuid
, self
.PackageList
, self
.MetaFile
.Path
)
2372 if Sku
.VariableGuidValue
== None:
2373 PackageList
= "\n\t".join([str(P
) for P
in self
.PackageList
])
2376 RESOURCE_NOT_AVAILABLE
,
2377 "Value of GUID [%s] is not found in" % Sku
.VariableGuid
,
2378 ExtraData
=PackageList
+ "\n\t(used with %s.%s from module %s)" \
2379 % (Guid
, Name
, str(Module
)),
2383 # override PCD settings with module specific setting
2384 if Module
in self
.Platform
.Modules
:
2385 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
2386 for Key
in PlatformModule
.Pcds
:
2391 elif Key
in GlobalData
.MixedPcd
:
2392 for PcdItem
in GlobalData
.MixedPcd
[Key
]:
2394 ToPcd
= Pcds
[PcdItem
]
2398 self
._OverridePcd
(ToPcd
, PlatformModule
.Pcds
[Key
], Module
)
2399 return Pcds
.values()
2401 ## Resolve library names to library modules
2403 # (for Edk.x modules)
2405 # @param Module The module from which the library names will be resolved
2407 # @retval library_list The list of library modules
2409 def ResolveLibraryReference(self
, Module
):
2410 EdkLogger
.verbose("")
2411 EdkLogger
.verbose("Library instances of module [%s] [%s]:" % (str(Module
), self
.Arch
))
2412 LibraryConsumerList
= [Module
]
2414 # "CompilerStub" is a must for Edk modules
2415 if Module
.Libraries
:
2416 Module
.Libraries
.append("CompilerStub")
2418 while len(LibraryConsumerList
) > 0:
2419 M
= LibraryConsumerList
.pop()
2420 for LibraryName
in M
.Libraries
:
2421 Library
= self
.Platform
.LibraryClasses
[LibraryName
, ':dummy:']
2423 for Key
in self
.Platform
.LibraryClasses
.data
.keys():
2424 if LibraryName
.upper() == Key
.upper():
2425 Library
= self
.Platform
.LibraryClasses
[Key
, ':dummy:']
2428 EdkLogger
.warn("build", "Library [%s] is not found" % LibraryName
, File
=str(M
),
2429 ExtraData
="\t%s [%s]" % (str(Module
), self
.Arch
))
2432 if Library
not in LibraryList
:
2433 LibraryList
.append(Library
)
2434 LibraryConsumerList
.append(Library
)
2435 EdkLogger
.verbose("\t" + LibraryName
+ " : " + str(Library
) + ' ' + str(type(Library
)))
2438 ## Calculate the priority value of the build option
2440 # @param Key Build option definition contain: TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
2442 # @retval Value Priority value based on the priority list.
2444 def CalculatePriorityValue(self
, Key
):
2445 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
.split('_')
2446 PriorityValue
= 0x11111
2448 PriorityValue
&= 0x01111
2449 if ToolChain
== "*":
2450 PriorityValue
&= 0x10111
2452 PriorityValue
&= 0x11011
2453 if CommandType
== "*":
2454 PriorityValue
&= 0x11101
2456 PriorityValue
&= 0x11110
2458 return self
.PrioList
["0x%0.5x" % PriorityValue
]
2461 ## Expand * in build option key
2463 # @param Options Options to be expanded
2465 # @retval options Options expanded
2467 def _ExpandBuildOption(self
, Options
, ModuleStyle
=None):
2474 # Construct a list contain the build options which need override.
2478 # Key[0] -- tool family
2479 # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
2481 if (Key
[0] == self
.BuildRuleFamily
and
2482 (ModuleStyle
== None or len(Key
) < 3 or (len(Key
) > 2 and Key
[2] == ModuleStyle
))):
2483 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
[1].split('_')
2484 if Target
== self
.BuildTarget
or Target
== "*":
2485 if ToolChain
== self
.ToolChain
or ToolChain
== "*":
2486 if Arch
== self
.Arch
or Arch
== "*":
2487 if Options
[Key
].startswith("="):
2488 if OverrideList
.get(Key
[1]) != None:
2489 OverrideList
.pop(Key
[1])
2490 OverrideList
[Key
[1]] = Options
[Key
]
2493 # Use the highest priority value.
2495 if (len(OverrideList
) >= 2):
2496 KeyList
= OverrideList
.keys()
2497 for Index
in range(len(KeyList
)):
2498 NowKey
= KeyList
[Index
]
2499 Target1
, ToolChain1
, Arch1
, CommandType1
, Attr1
= NowKey
.split("_")
2500 for Index1
in range(len(KeyList
) - Index
- 1):
2501 NextKey
= KeyList
[Index1
+ Index
+ 1]
2503 # Compare two Key, if one is included by another, choose the higher priority one
2505 Target2
, ToolChain2
, Arch2
, CommandType2
, Attr2
= NextKey
.split("_")
2506 if Target1
== Target2
or Target1
== "*" or Target2
== "*":
2507 if ToolChain1
== ToolChain2
or ToolChain1
== "*" or ToolChain2
== "*":
2508 if Arch1
== Arch2
or Arch1
== "*" or Arch2
== "*":
2509 if CommandType1
== CommandType2
or CommandType1
== "*" or CommandType2
== "*":
2510 if Attr1
== Attr2
or Attr1
== "*" or Attr2
== "*":
2511 if self
.CalculatePriorityValue(NowKey
) > self
.CalculatePriorityValue(NextKey
):
2512 if Options
.get((self
.BuildRuleFamily
, NextKey
)) != None:
2513 Options
.pop((self
.BuildRuleFamily
, NextKey
))
2515 if Options
.get((self
.BuildRuleFamily
, NowKey
)) != None:
2516 Options
.pop((self
.BuildRuleFamily
, NowKey
))
2519 if ModuleStyle
!= None and len (Key
) > 2:
2520 # Check Module style is EDK or EDKII.
2521 # Only append build option for the matched style module.
2522 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
2524 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
2527 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
2528 # if tool chain family doesn't match, skip it
2529 if Tool
in self
.ToolDefinition
and Family
!= "":
2530 FamilyIsNull
= False
2531 if self
.ToolDefinition
[Tool
].get(TAB_TOD_DEFINES_BUILDRULEFAMILY
, "") != "":
2532 if Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_BUILDRULEFAMILY
]:
2534 elif Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
2537 # expand any wildcard
2538 if Target
== "*" or Target
== self
.BuildTarget
:
2539 if Tag
== "*" or Tag
== self
.ToolChain
:
2540 if Arch
== "*" or Arch
== self
.Arch
:
2541 if Tool
not in BuildOptions
:
2542 BuildOptions
[Tool
] = {}
2543 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
] or Options
[Key
].startswith('='):
2544 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2546 # append options for the same tool except PATH
2548 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
2550 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2551 # Build Option Family has been checked, which need't to be checked again for family.
2552 if FamilyMatch
or FamilyIsNull
:
2556 if ModuleStyle
!= None and len (Key
) > 2:
2557 # Check Module style is EDK or EDKII.
2558 # Only append build option for the matched style module.
2559 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
2561 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
2564 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
2565 # if tool chain family doesn't match, skip it
2566 if Tool
not in self
.ToolDefinition
or Family
== "":
2568 # option has been added before
2569 if Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
2572 # expand any wildcard
2573 if Target
== "*" or Target
== self
.BuildTarget
:
2574 if Tag
== "*" or Tag
== self
.ToolChain
:
2575 if Arch
== "*" or Arch
== self
.Arch
:
2576 if Tool
not in BuildOptions
:
2577 BuildOptions
[Tool
] = {}
2578 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
] or Options
[Key
].startswith('='):
2579 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2581 # append options for the same tool except PATH
2583 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
2585 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2588 ## Append build options in platform to a module
2590 # @param Module The module to which the build options will be appened
2592 # @retval options The options appended with build options in platform
2594 def ApplyBuildOption(self
, Module
):
2595 # Get the different options for the different style module
2596 if Module
.AutoGenVersion
< 0x00010005:
2597 PlatformOptions
= self
.EdkBuildOption
2598 ModuleTypeOptions
= self
.Platform
.GetBuildOptionsByModuleType(EDK_NAME
, Module
.ModuleType
)
2600 PlatformOptions
= self
.EdkIIBuildOption
2601 ModuleTypeOptions
= self
.Platform
.GetBuildOptionsByModuleType(EDKII_NAME
, Module
.ModuleType
)
2602 ModuleTypeOptions
= self
._ExpandBuildOption
(ModuleTypeOptions
)
2603 ModuleOptions
= self
._ExpandBuildOption
(Module
.BuildOptions
)
2604 if Module
in self
.Platform
.Modules
:
2605 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
2606 PlatformModuleOptions
= self
._ExpandBuildOption
(PlatformModule
.BuildOptions
)
2608 PlatformModuleOptions
= {}
2610 BuildRuleOrder
= None
2611 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, ModuleTypeOptions
, PlatformModuleOptions
]:
2612 for Tool
in Options
:
2613 for Attr
in Options
[Tool
]:
2614 if Attr
== TAB_TOD_DEFINES_BUILDRULEORDER
:
2615 BuildRuleOrder
= Options
[Tool
][Attr
]
2617 AllTools
= set(ModuleOptions
.keys() + PlatformOptions
.keys() +
2618 PlatformModuleOptions
.keys() + ModuleTypeOptions
.keys() +
2619 self
.ToolDefinition
.keys())
2621 for Tool
in AllTools
:
2622 if Tool
not in BuildOptions
:
2623 BuildOptions
[Tool
] = {}
2625 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, ModuleTypeOptions
, PlatformModuleOptions
]:
2626 if Tool
not in Options
:
2628 for Attr
in Options
[Tool
]:
2629 Value
= Options
[Tool
][Attr
]
2631 # Do not generate it in Makefile
2633 if Attr
== TAB_TOD_DEFINES_BUILDRULEORDER
:
2635 if Attr
not in BuildOptions
[Tool
]:
2636 BuildOptions
[Tool
][Attr
] = ""
2637 # check if override is indicated
2638 if Value
.startswith('='):
2639 ToolPath
= Value
[1:]
2640 ToolPath
= mws
.handleWsMacro(ToolPath
)
2641 BuildOptions
[Tool
][Attr
] = ToolPath
2643 Value
= mws
.handleWsMacro(Value
)
2645 BuildOptions
[Tool
][Attr
] += " " + Value
2647 BuildOptions
[Tool
][Attr
] = Value
2648 if Module
.AutoGenVersion
< 0x00010005 and self
.Workspace
.UniFlag
!= None:
2650 # Override UNI flag only for EDK module.
2652 if 'BUILD' not in BuildOptions
:
2653 BuildOptions
['BUILD'] = {}
2654 BuildOptions
['BUILD']['FLAGS'] = self
.Workspace
.UniFlag
2655 return BuildOptions
, BuildRuleOrder
2657 Platform
= property(_GetPlatform
)
2658 Name
= property(_GetName
)
2659 Guid
= property(_GetGuid
)
2660 Version
= property(_GetVersion
)
2662 OutputDir
= property(_GetOutputDir
)
2663 BuildDir
= property(_GetBuildDir
)
2664 MakeFileDir
= property(_GetMakeFileDir
)
2665 FdfFile
= property(_GetFdfFile
)
2667 PcdTokenNumber
= property(_GetPcdTokenNumbers
) # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
2668 DynamicPcdList
= property(_GetDynamicPcdList
) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
2669 NonDynamicPcdList
= property(_GetNonDynamicPcdList
) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
2670 NonDynamicPcdDict
= property(_GetNonDynamicPcdDict
)
2671 PackageList
= property(_GetPackageList
)
2673 ToolDefinition
= property(_GetToolDefinition
) # toolcode : tool path
2674 ToolDefinitionFile
= property(_GetToolDefFile
) # toolcode : lib path
2675 ToolChainFamily
= property(_GetToolChainFamily
)
2676 BuildRuleFamily
= property(_GetBuildRuleFamily
)
2677 BuildOption
= property(_GetBuildOptions
) # toolcode : option
2678 EdkBuildOption
= property(_GetEdkBuildOptions
) # edktoolcode : option
2679 EdkIIBuildOption
= property(_GetEdkIIBuildOptions
) # edkiitoolcode : option
2681 BuildCommand
= property(_GetBuildCommand
)
2682 BuildRule
= property(_GetBuildRule
)
2683 ModuleAutoGenList
= property(_GetModuleAutoGenList
)
2684 LibraryAutoGenList
= property(_GetLibraryAutoGenList
)
2685 GenFdsCommand
= property(_GenFdsCommand
)
2687 ## ModuleAutoGen class
2689 # This class encapsules the AutoGen behaviors for the build tools. In addition to
2690 # the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according
2691 # to the [depex] section in module's inf file.
2693 class ModuleAutoGen(AutoGen
):
2694 ## Cache the timestamps of metafiles of every module in a class variable
2698 ## The real constructor of ModuleAutoGen
2700 # This method is not supposed to be called by users of ModuleAutoGen. It's
2701 # only used by factory method __new__() to do real initialization work for an
2702 # object of ModuleAutoGen
2704 # @param Workspace EdkIIWorkspaceBuild object
2705 # @param ModuleFile The path of module file
2706 # @param Target Build target (DEBUG, RELEASE)
2707 # @param Toolchain Name of tool chain
2708 # @param Arch The arch the module supports
2709 # @param PlatformFile Platform meta-file
2711 def _Init(self
, Workspace
, ModuleFile
, Target
, Toolchain
, Arch
, PlatformFile
):
2712 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen module [%s] [%s]" % (ModuleFile
, Arch
))
2713 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (ModuleFile
, Arch
, Toolchain
, Target
)
2715 self
.Workspace
= Workspace
2716 self
.WorkspaceDir
= Workspace
.WorkspaceDir
2718 self
.MetaFile
= ModuleFile
2719 self
.PlatformInfo
= PlatformAutoGen(Workspace
, PlatformFile
, Target
, Toolchain
, Arch
)
2720 # check if this module is employed by active platform
2721 if not self
.PlatformInfo
.ValidModule(self
.MetaFile
):
2722 EdkLogger
.verbose("Module [%s] for [%s] is not employed by active platform\n" \
2723 % (self
.MetaFile
, Arch
))
2726 self
.SourceDir
= self
.MetaFile
.SubDir
2727 self
.SourceDir
= mws
.relpath(self
.SourceDir
, self
.WorkspaceDir
)
2729 self
.SourceOverrideDir
= None
2730 # use overrided path defined in DSC file
2731 if self
.MetaFile
.Key
in GlobalData
.gOverrideDir
:
2732 self
.SourceOverrideDir
= GlobalData
.gOverrideDir
[self
.MetaFile
.Key
]
2734 self
.ToolChain
= Toolchain
2735 self
.BuildTarget
= Target
2737 self
.ToolChainFamily
= self
.PlatformInfo
.ToolChainFamily
2738 self
.BuildRuleFamily
= self
.PlatformInfo
.BuildRuleFamily
2740 self
.IsMakeFileCreated
= False
2741 self
.IsCodeFileCreated
= False
2742 self
.IsAsBuiltInfCreated
= False
2743 self
.DepexGenerated
= False
2745 self
.BuildDatabase
= self
.Workspace
.BuildDatabase
2746 self
.BuildRuleOrder
= None
2752 self
._Version
= None
2753 self
._ModuleType
= None
2754 self
._ComponentType
= None
2755 self
._PcdIsDriver
= None
2756 self
._AutoGenVersion
= None
2757 self
._LibraryFlag
= None
2758 self
._CustomMakefile
= None
2761 self
._BuildDir
= None
2762 self
._OutputDir
= None
2763 self
._FfsOutputDir
= None
2764 self
._DebugDir
= None
2765 self
._MakeFileDir
= None
2767 self
._IncludePathList
= None
2768 self
._IncludePathLength
= 0
2769 self
._AutoGenFileList
= None
2770 self
._UnicodeFileList
= None
2771 self
._VfrFileList
= None
2772 self
._IdfFileList
= None
2773 self
._SourceFileList
= None
2774 self
._ObjectFileList
= None
2775 self
._BinaryFileList
= None
2777 self
._DependentPackageList
= None
2778 self
._DependentLibraryList
= None
2779 self
._LibraryAutoGenList
= None
2780 self
._DerivedPackageList
= None
2781 self
._ModulePcdList
= None
2782 self
._LibraryPcdList
= None
2783 self
._PcdComments
= sdict()
2784 self
._GuidList
= None
2785 self
._GuidsUsedByPcd
= None
2786 self
._GuidComments
= sdict()
2787 self
._ProtocolList
= None
2788 self
._ProtocolComments
= sdict()
2789 self
._PpiList
= None
2790 self
._PpiComments
= sdict()
2791 self
._DepexList
= None
2792 self
._DepexExpressionList
= None
2793 self
._BuildOption
= None
2794 self
._BuildOptionIncPathList
= None
2795 self
._BuildTargets
= None
2796 self
._IntroBuildTargetList
= None
2797 self
._FinalBuildTargetList
= None
2798 self
._FileTypes
= None
2799 self
._BuildRules
= None
2801 self
._TimeStampPath
= None
2803 self
.AutoGenDepSet
= set()
2806 ## The Modules referenced to this Library
2807 # Only Library has this attribute
2808 self
._ReferenceModules
= []
2810 ## Store the FixedAtBuild Pcds
2812 self
._FixedAtBuildPcds
= []
2817 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
2819 # Get FixedAtBuild Pcds of this Module
2820 def _GetFixedAtBuildPcds(self
):
2821 if self
._FixedAtBuildPcds
:
2822 return self
._FixedAtBuildPcds
2823 for Pcd
in self
.ModulePcdList
:
2824 if Pcd
.Type
!= "FixedAtBuild":
2826 if Pcd
not in self
._FixedAtBuildPcds
:
2827 self
._FixedAtBuildPcds
.append(Pcd
)
2829 return self
._FixedAtBuildPcds
2831 def _GetUniqueBaseName(self
):
2832 BaseName
= self
.Name
2833 for Module
in self
.PlatformInfo
.ModuleAutoGenList
:
2834 if Module
.MetaFile
== self
.MetaFile
:
2836 if Module
.Name
== self
.Name
:
2837 if uuid
.UUID(Module
.Guid
) == uuid
.UUID(self
.Guid
):
2838 EdkLogger
.error("build", FILE_DUPLICATED
, 'Modules have same BaseName and FILE_GUID:\n'
2839 ' %s\n %s' % (Module
.MetaFile
, self
.MetaFile
))
2840 BaseName
= '%s_%s' % (self
.Name
, self
.Guid
)
2843 # Macros could be used in build_rule.txt (also Makefile)
2844 def _GetMacros(self
):
2845 if self
._Macro
== None:
2846 self
._Macro
= sdict()
2847 self
._Macro
["WORKSPACE" ] = self
.WorkspaceDir
2848 self
._Macro
["MODULE_NAME" ] = self
.Name
2849 self
._Macro
["MODULE_NAME_GUID" ] = self
._GetUniqueBaseName
()
2850 self
._Macro
["MODULE_GUID" ] = self
.Guid
2851 self
._Macro
["MODULE_VERSION" ] = self
.Version
2852 self
._Macro
["MODULE_TYPE" ] = self
.ModuleType
2853 self
._Macro
["MODULE_FILE" ] = str(self
.MetaFile
)
2854 self
._Macro
["MODULE_FILE_BASE_NAME" ] = self
.MetaFile
.BaseName
2855 self
._Macro
["MODULE_RELATIVE_DIR" ] = self
.SourceDir
2856 self
._Macro
["MODULE_DIR" ] = self
.SourceDir
2858 self
._Macro
["BASE_NAME" ] = self
.Name
2860 self
._Macro
["ARCH" ] = self
.Arch
2861 self
._Macro
["TOOLCHAIN" ] = self
.ToolChain
2862 self
._Macro
["TOOLCHAIN_TAG" ] = self
.ToolChain
2863 self
._Macro
["TOOL_CHAIN_TAG" ] = self
.ToolChain
2864 self
._Macro
["TARGET" ] = self
.BuildTarget
2866 self
._Macro
["BUILD_DIR" ] = self
.PlatformInfo
.BuildDir
2867 self
._Macro
["BIN_DIR" ] = os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)
2868 self
._Macro
["LIB_DIR" ] = os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)
2869 self
._Macro
["MODULE_BUILD_DIR" ] = self
.BuildDir
2870 self
._Macro
["OUTPUT_DIR" ] = self
.OutputDir
2871 self
._Macro
["DEBUG_DIR" ] = self
.DebugDir
2872 self
._Macro
["DEST_DIR_OUTPUT" ] = self
.OutputDir
2873 self
._Macro
["DEST_DIR_DEBUG" ] = self
.DebugDir
2874 self
._Macro
["PLATFORM_NAME" ] = self
.PlatformInfo
.Name
2875 self
._Macro
["PLATFORM_GUID" ] = self
.PlatformInfo
.Guid
2876 self
._Macro
["PLATFORM_VERSION" ] = self
.PlatformInfo
.Version
2877 self
._Macro
["PLATFORM_RELATIVE_DIR" ] = self
.PlatformInfo
.SourceDir
2878 self
._Macro
["PLATFORM_DIR" ] = mws
.join(self
.WorkspaceDir
, self
.PlatformInfo
.SourceDir
)
2879 self
._Macro
["PLATFORM_OUTPUT_DIR" ] = self
.PlatformInfo
.OutputDir
2880 self
._Macro
["FFS_OUTPUT_DIR" ] = self
.FfsOutputDir
2883 ## Return the module build data object
2884 def _GetModule(self
):
2885 if self
._Module
== None:
2886 self
._Module
= self
.Workspace
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
2889 ## Return the module name
2890 def _GetBaseName(self
):
2891 return self
.Module
.BaseName
2893 ## Return the module DxsFile if exist
2894 def _GetDxsFile(self
):
2895 return self
.Module
.DxsFile
2897 ## Return the module SourceOverridePath
2898 def _GetSourceOverridePath(self
):
2899 return self
.Module
.SourceOverridePath
2901 ## Return the module meta-file GUID
2904 # To build same module more than once, the module path with FILE_GUID overridden has
2905 # the file name FILE_GUIDmodule.inf, but the relative path (self.MetaFile.File) is the realy path
2906 # in DSC. The overridden GUID can be retrieved from file name
2908 if os
.path
.basename(self
.MetaFile
.File
) != os
.path
.basename(self
.MetaFile
.Path
):
2910 # Length of GUID is 36
2912 return os
.path
.basename(self
.MetaFile
.Path
)[:36]
2913 return self
.Module
.Guid
2915 ## Return the module version
2916 def _GetVersion(self
):
2917 return self
.Module
.Version
2919 ## Return the module type
2920 def _GetModuleType(self
):
2921 return self
.Module
.ModuleType
2923 ## Return the component type (for Edk.x style of module)
2924 def _GetComponentType(self
):
2925 return self
.Module
.ComponentType
2927 ## Return the build type
2928 def _GetBuildType(self
):
2929 return self
.Module
.BuildType
2931 ## Return the PCD_IS_DRIVER setting
2932 def _GetPcdIsDriver(self
):
2933 return self
.Module
.PcdIsDriver
2935 ## Return the autogen version, i.e. module meta-file version
2936 def _GetAutoGenVersion(self
):
2937 return self
.Module
.AutoGenVersion
2939 ## Check if the module is library or not
2940 def _IsLibrary(self
):
2941 if self
._LibraryFlag
== None:
2942 if self
.Module
.LibraryClass
!= None and self
.Module
.LibraryClass
!= []:
2943 self
._LibraryFlag
= True
2945 self
._LibraryFlag
= False
2946 return self
._LibraryFlag
2948 ## Check if the module is binary module or not
2949 def _IsBinaryModule(self
):
2950 return self
.Module
.IsBinaryModule
2952 ## Return the directory to store intermediate files of the module
2953 def _GetBuildDir(self
):
2954 if self
._BuildDir
== None:
2955 self
._BuildDir
= path
.join(
2956 self
.PlatformInfo
.BuildDir
,
2959 self
.MetaFile
.BaseName
2961 CreateDirectory(self
._BuildDir
)
2962 return self
._BuildDir
2964 ## Return the directory to store the intermediate object files of the mdoule
2965 def _GetOutputDir(self
):
2966 if self
._OutputDir
== None:
2967 self
._OutputDir
= path
.join(self
.BuildDir
, "OUTPUT")
2968 CreateDirectory(self
._OutputDir
)
2969 return self
._OutputDir
2971 ## Return the directory to store ffs file
2972 def _GetFfsOutputDir(self
):
2973 if self
._FfsOutputDir
== None:
2974 if GlobalData
.gFdfParser
!= None:
2975 self
._FfsOutputDir
= path
.join(self
.PlatformInfo
.BuildDir
, "FV", "Ffs", self
.Guid
+ self
.Name
)
2977 self
._FfsOutputDir
= ''
2978 return self
._FfsOutputDir
2980 ## Return the directory to store auto-gened source files of the mdoule
2981 def _GetDebugDir(self
):
2982 if self
._DebugDir
== None:
2983 self
._DebugDir
= path
.join(self
.BuildDir
, "DEBUG")
2984 CreateDirectory(self
._DebugDir
)
2985 return self
._DebugDir
2987 ## Return the path of custom file
2988 def _GetCustomMakefile(self
):
2989 if self
._CustomMakefile
== None:
2990 self
._CustomMakefile
= {}
2991 for Type
in self
.Module
.CustomMakefile
:
2992 if Type
in gMakeTypeMap
:
2993 MakeType
= gMakeTypeMap
[Type
]
2996 if self
.SourceOverrideDir
!= None:
2997 File
= os
.path
.join(self
.SourceOverrideDir
, self
.Module
.CustomMakefile
[Type
])
2998 if not os
.path
.exists(File
):
2999 File
= os
.path
.join(self
.SourceDir
, self
.Module
.CustomMakefile
[Type
])
3001 File
= os
.path
.join(self
.SourceDir
, self
.Module
.CustomMakefile
[Type
])
3002 self
._CustomMakefile
[MakeType
] = File
3003 return self
._CustomMakefile
3005 ## Return the directory of the makefile
3007 # @retval string The directory string of module's makefile
3009 def _GetMakeFileDir(self
):
3010 return self
.BuildDir
3012 ## Return build command string
3014 # @retval string Build command string
3016 def _GetBuildCommand(self
):
3017 return self
.PlatformInfo
.BuildCommand
3019 ## Get object list of all packages the module and its dependent libraries belong to
3021 # @retval list The list of package object
3023 def _GetDerivedPackageList(self
):
3025 for M
in [self
.Module
] + self
.DependentLibraryList
:
3026 for Package
in M
.Packages
:
3027 if Package
in PackageList
:
3029 PackageList
.append(Package
)
3032 ## Get the depex string
3034 # @return : a string contain all depex expresion.
3035 def _GetDepexExpresionString(self
):
3038 ## DPX_SOURCE IN Define section.
3039 if self
.Module
.DxsFile
:
3041 for M
in [self
.Module
] + self
.DependentLibraryList
:
3042 Filename
= M
.MetaFile
.Path
3043 InfObj
= InfSectionParser
.InfSectionParser(Filename
)
3044 DepexExpresionList
= InfObj
.GetDepexExpresionList()
3045 for DepexExpresion
in DepexExpresionList
:
3046 for key
in DepexExpresion
.keys():
3047 Arch
, ModuleType
= key
3048 DepexExpr
= [x
for x
in DepexExpresion
[key
] if not str(x
).startswith('#')]
3049 # the type of build module is USER_DEFINED.
3050 # All different DEPEX section tags would be copied into the As Built INF file
3051 # and there would be separate DEPEX section tags
3052 if self
.ModuleType
.upper() == SUP_MODULE_USER_DEFINED
:
3053 if (Arch
.upper() == self
.Arch
.upper()) and (ModuleType
.upper() != TAB_ARCH_COMMON
):
3054 DepexList
.append({(Arch
, ModuleType
): DepexExpr
})
3056 if Arch
.upper() == TAB_ARCH_COMMON
or \
3057 (Arch
.upper() == self
.Arch
.upper() and \
3058 ModuleType
.upper() in [TAB_ARCH_COMMON
, self
.ModuleType
.upper()]):
3059 DepexList
.append({(Arch
, ModuleType
): DepexExpr
})
3061 #the type of build module is USER_DEFINED.
3062 if self
.ModuleType
.upper() == SUP_MODULE_USER_DEFINED
:
3063 for Depex
in DepexList
:
3064 for key
in Depex
.keys():
3065 DepexStr
+= '[Depex.%s.%s]\n' % key
3066 DepexStr
+= '\n'.join(['# '+ val
for val
in Depex
[key
]])
3069 return '[Depex.%s]\n' % self
.Arch
3072 #the type of build module not is USER_DEFINED.
3074 for Depex
in DepexList
:
3079 for D
in Depex
.values():
3080 DepexStr
+= ' '.join([val
for val
in D
])
3081 Index
= DepexStr
.find('END')
3082 if Index
> -1 and Index
== len(DepexStr
) - 3:
3083 DepexStr
= DepexStr
[:-3]
3084 DepexStr
= DepexStr
.strip()
3087 DepexStr
= DepexStr
.lstrip('(').rstrip(')').strip()
3089 return '[Depex.%s]\n' % self
.Arch
3090 return '[Depex.%s]\n# ' % self
.Arch
+ DepexStr
3092 ## Merge dependency expression
3094 # @retval list The token list of the dependency expression after parsed
3096 def _GetDepexTokenList(self
):
3097 if self
._DepexList
== None:
3098 self
._DepexList
= {}
3099 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
3100 return self
._DepexList
3102 self
._DepexList
[self
.ModuleType
] = []
3104 for ModuleType
in self
._DepexList
:
3105 DepexList
= self
._DepexList
[ModuleType
]
3107 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
3109 for M
in [self
.Module
] + self
.DependentLibraryList
:
3111 for D
in M
.Depex
[self
.Arch
, ModuleType
]:
3113 DepexList
.append('AND')
3114 DepexList
.append('(')
3116 if DepexList
[-1] == 'END': # no need of a END at this time
3118 DepexList
.append(')')
3121 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexList
))
3122 if 'BEFORE' in DepexList
or 'AFTER' in DepexList
:
3124 if len(DepexList
) > 0:
3125 EdkLogger
.verbose('')
3126 return self
._DepexList
3128 ## Merge dependency expression
3130 # @retval list The token list of the dependency expression after parsed
3132 def _GetDepexExpressionTokenList(self
):
3133 if self
._DepexExpressionList
== None:
3134 self
._DepexExpressionList
= {}
3135 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
3136 return self
._DepexExpressionList
3138 self
._DepexExpressionList
[self
.ModuleType
] = ''
3140 for ModuleType
in self
._DepexExpressionList
:
3141 DepexExpressionList
= self
._DepexExpressionList
[ModuleType
]
3143 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
3145 for M
in [self
.Module
] + self
.DependentLibraryList
:
3147 for D
in M
.DepexExpression
[self
.Arch
, ModuleType
]:
3148 if DepexExpressionList
!= '':
3149 DepexExpressionList
+= ' AND '
3150 DepexExpressionList
+= '('
3151 DepexExpressionList
+= D
3152 DepexExpressionList
= DepexExpressionList
.rstrip('END').strip()
3153 DepexExpressionList
+= ')'
3156 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexExpressionList
))
3157 if 'BEFORE' in DepexExpressionList
or 'AFTER' in DepexExpressionList
:
3159 if len(DepexExpressionList
) > 0:
3160 EdkLogger
.verbose('')
3161 self
._DepexExpressionList
[ModuleType
] = DepexExpressionList
3162 return self
._DepexExpressionList
3164 # Get the tiano core user extension, it is contain dependent library.
3165 # @retval: a list contain tiano core userextension.
3167 def _GetTianoCoreUserExtensionList(self
):
3168 TianoCoreUserExtentionList
= []
3169 for M
in [self
.Module
] + self
.DependentLibraryList
:
3170 Filename
= M
.MetaFile
.Path
3171 InfObj
= InfSectionParser
.InfSectionParser(Filename
)
3172 TianoCoreUserExtenList
= InfObj
.GetUserExtensionTianoCore()
3173 for TianoCoreUserExtent
in TianoCoreUserExtenList
:
3174 for Section
in TianoCoreUserExtent
.keys():
3175 ItemList
= Section
.split(TAB_SPLIT
)
3177 if len(ItemList
) == 4:
3179 if Arch
.upper() == TAB_ARCH_COMMON
or Arch
.upper() == self
.Arch
.upper():
3181 TianoCoreList
.extend([TAB_SECTION_START
+ Section
+ TAB_SECTION_END
])
3182 TianoCoreList
.extend(TianoCoreUserExtent
[Section
][:])
3183 TianoCoreList
.append('\n')
3184 TianoCoreUserExtentionList
.append(TianoCoreList
)
3186 return TianoCoreUserExtentionList
3188 ## Return the list of specification version required for the module
3190 # @retval list The list of specification defined in module file
3192 def _GetSpecification(self
):
3193 return self
.Module
.Specification
3195 ## Tool option for the module build
3197 # @param PlatformInfo The object of PlatformBuildInfo
3198 # @retval dict The dict containing valid options
3200 def _GetModuleBuildOption(self
):
3201 if self
._BuildOption
== None:
3202 self
._BuildOption
, self
.BuildRuleOrder
= self
.PlatformInfo
.ApplyBuildOption(self
.Module
)
3203 if self
.BuildRuleOrder
:
3204 self
.BuildRuleOrder
= ['.%s' % Ext
for Ext
in self
.BuildRuleOrder
.split()]
3205 return self
._BuildOption
3207 ## Get include path list from tool option for the module build
3209 # @retval list The include path list
3211 def _GetBuildOptionIncPathList(self
):
3212 if self
._BuildOptionIncPathList
== None:
3214 # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
3215 # is the former use /I , the Latter used -I to specify include directories
3217 if self
.PlatformInfo
.ToolChainFamily
in ('MSFT'):
3218 gBuildOptIncludePattern
= re
.compile(r
"(?:.*?)/I[ \t]*([^ ]*)", re
.MULTILINE | re
.DOTALL
)
3219 elif self
.PlatformInfo
.ToolChainFamily
in ('INTEL', 'GCC', 'RVCT'):
3220 gBuildOptIncludePattern
= re
.compile(r
"(?:.*?)-I[ \t]*([^ ]*)", re
.MULTILINE | re
.DOTALL
)
3223 # New ToolChainFamily, don't known whether there is option to specify include directories
3225 self
._BuildOptionIncPathList
= []
3226 return self
._BuildOptionIncPathList
3228 BuildOptionIncPathList
= []
3229 for Tool
in ('CC', 'PP', 'VFRPP', 'ASLPP', 'ASLCC', 'APP', 'ASM'):
3232 FlagOption
= self
.BuildOption
[Tool
][Attr
]
3236 if self
.PlatformInfo
.ToolChainFamily
!= 'RVCT':
3237 IncPathList
= [NormPath(Path
, self
.Macros
) for Path
in gBuildOptIncludePattern
.findall(FlagOption
)]
3240 # RVCT may specify a list of directory seperated by commas
3243 for Path
in gBuildOptIncludePattern
.findall(FlagOption
):
3244 PathList
= GetSplitList(Path
, TAB_COMMA_SPLIT
)
3245 IncPathList
+= [NormPath(PathEntry
, self
.Macros
) for PathEntry
in PathList
]
3248 # EDK II modules must not reference header files outside of the packages they depend on or
3249 # within the module's directory tree. Report error if violation.
3251 if self
.AutoGenVersion
>= 0x00010005 and len(IncPathList
) > 0:
3252 for Path
in IncPathList
:
3253 if (Path
not in self
.IncludePathList
) and (CommonPath([Path
, self
.MetaFile
.Dir
]) != self
.MetaFile
.Dir
):
3254 ErrMsg
= "The include directory for the EDK II module in this line is invalid %s specified in %s FLAGS '%s'" % (Path
, Tool
, FlagOption
)
3255 EdkLogger
.error("build",
3258 File
=str(self
.MetaFile
))
3261 BuildOptionIncPathList
+= IncPathList
3263 self
._BuildOptionIncPathList
= BuildOptionIncPathList
3265 return self
._BuildOptionIncPathList
3267 ## Return a list of files which can be built from source
3269 # What kind of files can be built is determined by build rules in
3270 # $(CONF_DIRECTORY)/build_rule.txt and toolchain family.
3272 def _GetSourceFileList(self
):
3273 if self
._SourceFileList
== None:
3274 self
._SourceFileList
= []
3275 for F
in self
.Module
.Sources
:
3277 if F
.TagName
not in ("", "*", self
.ToolChain
):
3278 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "The toolchain [%s] for processing file [%s] is found, "
3279 "but [%s] is needed" % (F
.TagName
, str(F
), self
.ToolChain
))
3281 # match tool chain family or build rule family
3282 if F
.ToolChainFamily
not in ("", "*", self
.ToolChainFamily
, self
.BuildRuleFamily
):
3285 "The file [%s] must be built by tools of [%s], " \
3286 "but current toolchain family is [%s], buildrule family is [%s]" \
3287 % (str(F
), F
.ToolChainFamily
, self
.ToolChainFamily
, self
.BuildRuleFamily
))
3290 # add the file path into search path list for file including
3291 if F
.Dir
not in self
.IncludePathList
and self
.AutoGenVersion
>= 0x00010005:
3292 self
.IncludePathList
.insert(0, F
.Dir
)
3293 self
._SourceFileList
.append(F
)
3295 self
._MatchBuildRuleOrder
(self
._SourceFileList
)
3297 for F
in self
._SourceFileList
:
3298 self
._ApplyBuildRule
(F
, TAB_UNKNOWN_FILE
)
3299 return self
._SourceFileList
3301 def _MatchBuildRuleOrder(self
, FileList
):
3303 self
._GetModuleBuildOption
()
3304 for SingleFile
in FileList
:
3305 if self
.BuildRuleOrder
and SingleFile
.Ext
in self
.BuildRuleOrder
and SingleFile
.Ext
in self
.BuildRules
:
3306 key
= SingleFile
.Path
.split(SingleFile
.Ext
)[0]
3307 if key
in Order_Dict
:
3308 Order_Dict
[key
].append(SingleFile
.Ext
)
3310 Order_Dict
[key
] = [SingleFile
.Ext
]
3313 for F
in Order_Dict
:
3314 if len(Order_Dict
[F
]) > 1:
3315 Order_Dict
[F
].sort(key
=lambda i
: self
.BuildRuleOrder
.index(i
))
3316 for Ext
in Order_Dict
[F
][1:]:
3317 RemoveList
.append(F
+ Ext
)
3319 for item
in RemoveList
:
3320 FileList
.remove(item
)
3324 ## Return the list of unicode files
3325 def _GetUnicodeFileList(self
):
3326 if self
._UnicodeFileList
== None:
3327 if TAB_UNICODE_FILE
in self
.FileTypes
:
3328 self
._UnicodeFileList
= self
.FileTypes
[TAB_UNICODE_FILE
]
3330 self
._UnicodeFileList
= []
3331 return self
._UnicodeFileList
3333 ## Return the list of vfr files
3334 def _GetVfrFileList(self
):
3335 if self
._VfrFileList
== None:
3336 if TAB_VFR_FILE
in self
.FileTypes
:
3337 self
._VfrFileList
= self
.FileTypes
[TAB_VFR_FILE
]
3339 self
._VfrFileList
= []
3340 return self
._VfrFileList
3342 ## Return the list of Image Definition files
3343 def _GetIdfFileList(self
):
3344 if self
._IdfFileList
== None:
3345 if TAB_IMAGE_FILE
in self
.FileTypes
:
3346 self
._IdfFileList
= self
.FileTypes
[TAB_IMAGE_FILE
]
3348 self
._IdfFileList
= []
3349 return self
._IdfFileList
3351 ## Return a list of files which can be built from binary
3353 # "Build" binary files are just to copy them to build directory.
3355 # @retval list The list of files which can be built later
3357 def _GetBinaryFiles(self
):
3358 if self
._BinaryFileList
== None:
3359 self
._BinaryFileList
= []
3360 for F
in self
.Module
.Binaries
:
3361 if F
.Target
not in ['COMMON', '*'] and F
.Target
!= self
.BuildTarget
:
3363 self
._BinaryFileList
.append(F
)
3364 self
._ApplyBuildRule
(F
, F
.Type
)
3365 return self
._BinaryFileList
3367 def _GetBuildRules(self
):
3368 if self
._BuildRules
== None:
3370 BuildRuleDatabase
= self
.PlatformInfo
.BuildRule
3371 for Type
in BuildRuleDatabase
.FileTypeList
:
3372 #first try getting build rule by BuildRuleFamily
3373 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.BuildRuleFamily
]
3375 # build type is always module type, but ...
3376 if self
.ModuleType
!= self
.BuildType
:
3377 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.BuildRuleFamily
]
3378 #second try getting build rule by ToolChainFamily
3380 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.ToolChainFamily
]
3382 # build type is always module type, but ...
3383 if self
.ModuleType
!= self
.BuildType
:
3384 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.ToolChainFamily
]
3387 RuleObject
= RuleObject
.Instantiate(self
.Macros
)
3388 BuildRules
[Type
] = RuleObject
3389 for Ext
in RuleObject
.SourceFileExtList
:
3390 BuildRules
[Ext
] = RuleObject
3391 self
._BuildRules
= BuildRules
3392 return self
._BuildRules
3394 def _ApplyBuildRule(self
, File
, FileType
):
3395 if self
._BuildTargets
== None:
3396 self
._IntroBuildTargetList
= set()
3397 self
._FinalBuildTargetList
= set()
3398 self
._BuildTargets
= {}
3399 self
._FileTypes
= {}
3401 SubDirectory
= os
.path
.join(self
.OutputDir
, File
.SubDir
)
3402 if not os
.path
.exists(SubDirectory
):
3403 CreateDirectory(SubDirectory
)
3409 # Make sure to get build rule order value
3411 self
._GetModuleBuildOption
()
3413 while Index
< len(SourceList
):
3414 Source
= SourceList
[Index
]
3418 CreateDirectory(Source
.Dir
)
3420 if File
.IsBinary
and File
== Source
and self
._BinaryFileList
!= None and File
in self
._BinaryFileList
:
3421 # Skip all files that are not binary libraries
3422 if not self
.IsLibrary
:
3424 RuleObject
= self
.BuildRules
[TAB_DEFAULT_BINARY_FILE
]
3425 elif FileType
in self
.BuildRules
:
3426 RuleObject
= self
.BuildRules
[FileType
]
3427 elif Source
.Ext
in self
.BuildRules
:
3428 RuleObject
= self
.BuildRules
[Source
.Ext
]
3430 # stop at no more rules
3432 self
._FinalBuildTargetList
.add(LastTarget
)
3435 FileType
= RuleObject
.SourceFileType
3436 if FileType
not in self
._FileTypes
:
3437 self
._FileTypes
[FileType
] = set()
3438 self
._FileTypes
[FileType
].add(Source
)
3440 # stop at STATIC_LIBRARY for library
3441 if self
.IsLibrary
and FileType
== TAB_STATIC_LIBRARY
:
3443 self
._FinalBuildTargetList
.add(LastTarget
)
3446 Target
= RuleObject
.Apply(Source
, self
.BuildRuleOrder
)
3449 self
._FinalBuildTargetList
.add(LastTarget
)
3451 elif not Target
.Outputs
:
3452 # Only do build for target with outputs
3453 self
._FinalBuildTargetList
.add(Target
)
3455 if FileType
not in self
._BuildTargets
:
3456 self
._BuildTargets
[FileType
] = set()
3457 self
._BuildTargets
[FileType
].add(Target
)
3459 if not Source
.IsBinary
and Source
== File
:
3460 self
._IntroBuildTargetList
.add(Target
)
3462 # to avoid cyclic rule
3463 if FileType
in RuleChain
:
3466 RuleChain
.append(FileType
)
3467 SourceList
.extend(Target
.Outputs
)
3469 FileType
= TAB_UNKNOWN_FILE
3471 def _GetTargets(self
):
3472 if self
._BuildTargets
== None:
3473 self
._IntroBuildTargetList
= set()
3474 self
._FinalBuildTargetList
= set()
3475 self
._BuildTargets
= {}
3476 self
._FileTypes
= {}
3478 #TRICK: call _GetSourceFileList to apply build rule for source files
3479 if self
.SourceFileList
:
3482 #TRICK: call _GetBinaryFileList to apply build rule for binary files
3483 if self
.BinaryFileList
:
3486 return self
._BuildTargets
3488 def _GetIntroTargetList(self
):
3490 return self
._IntroBuildTargetList
3492 def _GetFinalTargetList(self
):
3494 return self
._FinalBuildTargetList
3496 def _GetFileTypes(self
):
3498 return self
._FileTypes
3500 ## Get the list of package object the module depends on
3502 # @retval list The package object list
3504 def _GetDependentPackageList(self
):
3505 return self
.Module
.Packages
3507 ## Return the list of auto-generated code file
3509 # @retval list The list of auto-generated file
3511 def _GetAutoGenFileList(self
):
3512 UniStringAutoGenC
= True
3513 IdfStringAutoGenC
= True
3514 UniStringBinBuffer
= StringIO()
3515 IdfGenBinBuffer
= StringIO()
3516 if self
.BuildType
== 'UEFI_HII':
3517 UniStringAutoGenC
= False
3518 IdfStringAutoGenC
= False
3519 if self
._AutoGenFileList
== None:
3520 self
._AutoGenFileList
= {}
3521 AutoGenC
= TemplateString()
3522 AutoGenH
= TemplateString()
3523 StringH
= TemplateString()
3524 StringIdf
= TemplateString()
3525 GenC
.CreateCode(self
, AutoGenC
, AutoGenH
, StringH
, UniStringAutoGenC
, UniStringBinBuffer
, StringIdf
, IdfStringAutoGenC
, IdfGenBinBuffer
)
3527 # AutoGen.c is generated if there are library classes in inf, or there are object files
3529 if str(AutoGenC
) != "" and (len(self
.Module
.LibraryClasses
) > 0
3530 or TAB_OBJECT_FILE
in self
.FileTypes
):
3531 AutoFile
= PathClass(gAutoGenCodeFileName
, self
.DebugDir
)
3532 self
._AutoGenFileList
[AutoFile
] = str(AutoGenC
)
3533 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3534 if str(AutoGenH
) != "":
3535 AutoFile
= PathClass(gAutoGenHeaderFileName
, self
.DebugDir
)
3536 self
._AutoGenFileList
[AutoFile
] = str(AutoGenH
)
3537 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3538 if str(StringH
) != "":
3539 AutoFile
= PathClass(gAutoGenStringFileName
% {"module_name":self
.Name
}, self
.DebugDir
)
3540 self
._AutoGenFileList
[AutoFile
] = str(StringH
)
3541 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3542 if UniStringBinBuffer
!= None and UniStringBinBuffer
.getvalue() != "":
3543 AutoFile
= PathClass(gAutoGenStringFormFileName
% {"module_name":self
.Name
}, self
.OutputDir
)
3544 self
._AutoGenFileList
[AutoFile
] = UniStringBinBuffer
.getvalue()
3545 AutoFile
.IsBinary
= True
3546 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3547 if UniStringBinBuffer
!= None:
3548 UniStringBinBuffer
.close()
3549 if str(StringIdf
) != "":
3550 AutoFile
= PathClass(gAutoGenImageDefFileName
% {"module_name":self
.Name
}, self
.DebugDir
)
3551 self
._AutoGenFileList
[AutoFile
] = str(StringIdf
)
3552 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3553 if IdfGenBinBuffer
!= None and IdfGenBinBuffer
.getvalue() != "":
3554 AutoFile
= PathClass(gAutoGenIdfFileName
% {"module_name":self
.Name
}, self
.OutputDir
)
3555 self
._AutoGenFileList
[AutoFile
] = IdfGenBinBuffer
.getvalue()
3556 AutoFile
.IsBinary
= True
3557 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3558 if IdfGenBinBuffer
!= None:
3559 IdfGenBinBuffer
.close()
3560 return self
._AutoGenFileList
3562 ## Return the list of library modules explicitly or implicityly used by this module
3563 def _GetLibraryList(self
):
3564 if self
._DependentLibraryList
== None:
3565 # only merge library classes and PCD for non-library module
3567 self
._DependentLibraryList
= []
3569 if self
.AutoGenVersion
< 0x00010005:
3570 self
._DependentLibraryList
= self
.PlatformInfo
.ResolveLibraryReference(self
.Module
)
3572 self
._DependentLibraryList
= self
.PlatformInfo
.ApplyLibraryInstance(self
.Module
)
3573 return self
._DependentLibraryList
3576 def UpdateComments(Recver
, Src
):
3578 if Key
not in Recver
:
3580 Recver
[Key
].extend(Src
[Key
])
3581 ## Get the list of PCDs from current module
3583 # @retval list The list of PCD
3585 def _GetModulePcdList(self
):
3586 if self
._ModulePcdList
== None:
3587 # apply PCD settings from platform
3588 self
._ModulePcdList
= self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, self
.Module
.Pcds
)
3589 self
.UpdateComments(self
._PcdComments
, self
.Module
.PcdComments
)
3590 return self
._ModulePcdList
3592 ## Get the list of PCDs from dependent libraries
3594 # @retval list The list of PCD
3596 def _GetLibraryPcdList(self
):
3597 if self
._LibraryPcdList
== None:
3599 if not self
.IsLibrary
:
3600 # get PCDs from dependent libraries
3601 for Library
in self
.DependentLibraryList
:
3602 self
.UpdateComments(self
._PcdComments
, Library
.PcdComments
)
3603 for Key
in Library
.Pcds
:
3604 # skip duplicated PCDs
3605 if Key
in self
.Module
.Pcds
or Key
in Pcds
:
3607 Pcds
[Key
] = copy
.copy(Library
.Pcds
[Key
])
3608 # apply PCD settings from platform
3609 self
._LibraryPcdList
= self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, Pcds
)
3611 self
._LibraryPcdList
= []
3612 return self
._LibraryPcdList
3614 ## Get the GUID value mapping
3616 # @retval dict The mapping between GUID cname and its value
3618 def _GetGuidList(self
):
3619 if self
._GuidList
== None:
3620 self
._GuidList
= sdict()
3621 self
._GuidList
.update(self
.Module
.Guids
)
3622 for Library
in self
.DependentLibraryList
:
3623 self
._GuidList
.update(Library
.Guids
)
3624 self
.UpdateComments(self
._GuidComments
, Library
.GuidComments
)
3625 self
.UpdateComments(self
._GuidComments
, self
.Module
.GuidComments
)
3626 return self
._GuidList
3628 def GetGuidsUsedByPcd(self
):
3629 if self
._GuidsUsedByPcd
== None:
3630 self
._GuidsUsedByPcd
= sdict()
3631 self
._GuidsUsedByPcd
.update(self
.Module
.GetGuidsUsedByPcd())
3632 for Library
in self
.DependentLibraryList
:
3633 self
._GuidsUsedByPcd
.update(Library
.GetGuidsUsedByPcd())
3634 return self
._GuidsUsedByPcd
3635 ## Get the protocol value mapping
3637 # @retval dict The mapping between protocol cname and its value
3639 def _GetProtocolList(self
):
3640 if self
._ProtocolList
== None:
3641 self
._ProtocolList
= sdict()
3642 self
._ProtocolList
.update(self
.Module
.Protocols
)
3643 for Library
in self
.DependentLibraryList
:
3644 self
._ProtocolList
.update(Library
.Protocols
)
3645 self
.UpdateComments(self
._ProtocolComments
, Library
.ProtocolComments
)
3646 self
.UpdateComments(self
._ProtocolComments
, self
.Module
.ProtocolComments
)
3647 return self
._ProtocolList
3649 ## Get the PPI value mapping
3651 # @retval dict The mapping between PPI cname and its value
3653 def _GetPpiList(self
):
3654 if self
._PpiList
== None:
3655 self
._PpiList
= sdict()
3656 self
._PpiList
.update(self
.Module
.Ppis
)
3657 for Library
in self
.DependentLibraryList
:
3658 self
._PpiList
.update(Library
.Ppis
)
3659 self
.UpdateComments(self
._PpiComments
, Library
.PpiComments
)
3660 self
.UpdateComments(self
._PpiComments
, self
.Module
.PpiComments
)
3661 return self
._PpiList
3663 ## Get the list of include search path
3665 # @retval list The list path
3667 def _GetIncludePathList(self
):
3668 if self
._IncludePathList
== None:
3669 self
._IncludePathList
= []
3670 if self
.AutoGenVersion
< 0x00010005:
3671 for Inc
in self
.Module
.Includes
:
3672 if Inc
not in self
._IncludePathList
:
3673 self
._IncludePathList
.append(Inc
)
3675 Inc
= path
.join(Inc
, self
.Arch
.capitalize())
3676 if os
.path
.exists(Inc
) and Inc
not in self
._IncludePathList
:
3677 self
._IncludePathList
.append(Inc
)
3678 # Edk module needs to put DEBUG_DIR at the end of search path and not to use SOURCE_DIR all the time
3679 self
._IncludePathList
.append(self
.DebugDir
)
3681 self
._IncludePathList
.append(self
.MetaFile
.Dir
)
3682 self
._IncludePathList
.append(self
.DebugDir
)
3684 for Package
in self
.Module
.Packages
:
3685 PackageDir
= mws
.join(self
.WorkspaceDir
, Package
.MetaFile
.Dir
)
3686 if PackageDir
not in self
._IncludePathList
:
3687 self
._IncludePathList
.append(PackageDir
)
3688 IncludesList
= Package
.Includes
3689 if Package
._PrivateIncludes
:
3690 if not self
.MetaFile
.Path
.startswith(PackageDir
):
3691 IncludesList
= list(set(Package
.Includes
).difference(set(Package
._PrivateIncludes
)))
3692 for Inc
in IncludesList
:
3693 if Inc
not in self
._IncludePathList
:
3694 self
._IncludePathList
.append(str(Inc
))
3695 return self
._IncludePathList
3697 def _GetIncludePathLength(self
):
3698 self
._IncludePathLength
= 0
3699 if self
._IncludePathList
:
3700 for inc
in self
._IncludePathList
:
3701 self
._IncludePathLength
+= len(' ' + inc
)
3702 return self
._IncludePathLength
3704 ## Get HII EX PCDs which maybe used by VFR
3706 # efivarstore used by VFR may relate with HII EX PCDs
3707 # Get the variable name and GUID from efivarstore and HII EX PCD
3708 # List the HII EX PCDs in As Built INF if both name and GUID match.
3710 # @retval list HII EX PCDs
3712 def _GetPcdsMaybeUsedByVfr(self
):
3713 if not self
.SourceFileList
:
3717 for SrcFile
in self
.SourceFileList
:
3718 if SrcFile
.Ext
.lower() != '.vfr':
3720 Vfri
= os
.path
.join(self
.OutputDir
, SrcFile
.BaseName
+ '.i')
3721 if not os
.path
.exists(Vfri
):
3723 VfriFile
= open(Vfri
, 'r')
3724 Content
= VfriFile
.read()
3726 Pos
= Content
.find('efivarstore')
3729 # Make sure 'efivarstore' is the start of efivarstore statement
3730 # In case of the value of 'name' (name = efivarstore) is equal to 'efivarstore'
3733 while Index
>= 0 and Content
[Index
] in ' \t\r\n':
3735 if Index
>= 0 and Content
[Index
] != ';':
3736 Pos
= Content
.find('efivarstore', Pos
+ len('efivarstore'))
3739 # 'efivarstore' must be followed by name and guid
3741 Name
= gEfiVarStoreNamePattern
.search(Content
, Pos
)
3744 Guid
= gEfiVarStoreGuidPattern
.search(Content
, Pos
)
3747 NameArray
= ConvertStringToByteArray('L"' + Name
.group(1) + '"')
3748 NameGuids
.append((NameArray
, GuidStructureStringToGuidString(Guid
.group(1))))
3749 Pos
= Content
.find('efivarstore', Name
.end())
3753 for Pcd
in self
.PlatformInfo
.Platform
.Pcds
.values():
3754 if Pcd
.Type
!= TAB_PCDS_DYNAMIC_EX_HII
:
3756 for SkuName
in Pcd
.SkuInfoList
:
3757 SkuInfo
= Pcd
.SkuInfoList
[SkuName
]
3758 Name
= ConvertStringToByteArray(SkuInfo
.VariableName
)
3759 Value
= GuidValue(SkuInfo
.VariableGuid
, self
.PlatformInfo
.PackageList
, self
.MetaFile
.Path
)
3762 Guid
= GuidStructureStringToGuidString(Value
)
3763 if (Name
, Guid
) in NameGuids
and Pcd
not in HiiExPcds
:
3764 HiiExPcds
.append(Pcd
)
3769 def _GenOffsetBin(self
):
3771 for SourceFile
in self
.Module
.Sources
:
3772 if SourceFile
.Type
.upper() == ".VFR" :
3774 # search the .map file to find the offset of vfr binary in the PE32+/TE file.
3776 VfrUniBaseName
[SourceFile
.BaseName
] = (SourceFile
.BaseName
+ "Bin")
3777 if SourceFile
.Type
.upper() == ".UNI" :
3779 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
3781 VfrUniBaseName
["UniOffsetName"] = (self
.Name
+ "Strings")
3783 if len(VfrUniBaseName
) == 0:
3785 MapFileName
= os
.path
.join(self
.OutputDir
, self
.Name
+ ".map")
3786 EfiFileName
= os
.path
.join(self
.OutputDir
, self
.Name
+ ".efi")
3787 VfrUniOffsetList
= GetVariableOffset(MapFileName
, EfiFileName
, VfrUniBaseName
.values())
3788 if not VfrUniOffsetList
:
3791 OutputName
= '%sOffset.bin' % self
.Name
3792 UniVfrOffsetFileName
= os
.path
.join( self
.OutputDir
, OutputName
)
3795 fInputfile
= open(UniVfrOffsetFileName
, "wb+", 0)
3797 EdkLogger
.error("build", FILE_OPEN_FAILURE
, "File open failed for %s" % UniVfrOffsetFileName
,None)
3799 # Use a instance of StringIO to cache data
3800 fStringIO
= StringIO('')
3802 for Item
in VfrUniOffsetList
:
3803 if (Item
[0].find("Strings") != -1):
3805 # UNI offset in image.
3807 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }
3809 UniGuid
= [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66]
3810 UniGuid
= [chr(ItemGuid
) for ItemGuid
in UniGuid
]
3811 fStringIO
.write(''.join(UniGuid
))
3812 UniValue
= pack ('Q', int (Item
[1], 16))
3813 fStringIO
.write (UniValue
)
3816 # VFR binary offset in image.
3818 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };
3820 VfrGuid
= [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2]
3821 VfrGuid
= [chr(ItemGuid
) for ItemGuid
in VfrGuid
]
3822 fStringIO
.write(''.join(VfrGuid
))
3824 VfrValue
= pack ('Q', int (Item
[1], 16))
3825 fStringIO
.write (VfrValue
)
3827 # write data into file.
3830 fInputfile
.write (fStringIO
.getvalue())
3832 EdkLogger
.error("build", FILE_WRITE_FAILURE
, "Write data to file %s failed, please check whether the "
3833 "file been locked or using by other applications." %UniVfrOffsetFileName
,None)
3839 ## Create AsBuilt INF file the module
3841 def CreateAsBuiltInf(self
, IsOnlyCopy
= False):
3842 self
.OutputFile
= []
3844 if GlobalData
.gBinCacheDest
:
3845 self
.CopyModuleToCache()
3848 if self
.IsAsBuiltInfCreated
:
3851 # Skip the following code for EDK I inf
3852 if self
.AutoGenVersion
< 0x00010005:
3855 # Skip the following code for libraries
3859 # Skip the following code for modules with no source files
3860 if self
.SourceFileList
== None or self
.SourceFileList
== []:
3863 # Skip the following code for modules without any binary files
3864 if self
.BinaryFileList
<> None and self
.BinaryFileList
<> []:
3867 ### TODO: How to handles mixed source and binary modules
3869 # Find all DynamicEx and PatchableInModule PCDs used by this module and dependent libraries
3870 # Also find all packages that the DynamicEx PCDs depend on
3875 PcdTokenSpaceList
= []
3876 for Pcd
in self
.ModulePcdList
+ self
.LibraryPcdList
:
3877 if Pcd
.Type
== TAB_PCDS_PATCHABLE_IN_MODULE
:
3878 PatchablePcds
+= [Pcd
]
3879 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, 'PatchableInModule'))
3880 elif Pcd
.Type
in GenC
.gDynamicExPcd
:
3883 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, 'DynamicEx'))
3884 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, 'Dynamic'))
3885 PcdTokenSpaceList
.append(Pcd
.TokenSpaceGuidCName
)
3887 GuidList
.update(self
.GuidList
)
3888 for TokenSpace
in self
.GetGuidsUsedByPcd():
3889 # If token space is not referred by patch PCD or Ex PCD, remove the GUID from GUID list
3890 # The GUIDs in GUIDs section should really be the GUIDs in source INF or referred by Ex an patch PCDs
3891 if TokenSpace
not in PcdTokenSpaceList
and TokenSpace
in GuidList
:
3892 GuidList
.pop(TokenSpace
)
3893 CheckList
= (GuidList
, self
.PpiList
, self
.ProtocolList
, PcdCheckList
)
3894 for Package
in self
.DerivedPackageList
:
3895 if Package
in Packages
:
3897 BeChecked
= (Package
.Guids
, Package
.Ppis
, Package
.Protocols
, Package
.Pcds
)
3899 for Index
in range(len(BeChecked
)):
3900 for Item
in CheckList
[Index
]:
3901 if Item
in BeChecked
[Index
]:
3902 Packages
+= [Package
]
3907 VfrPcds
= self
._GetPcdsMaybeUsedByVfr
()
3908 for Pkg
in self
.PlatformInfo
.PackageList
:
3911 for VfrPcd
in VfrPcds
:
3912 if ((VfrPcd
.TokenCName
, VfrPcd
.TokenSpaceGuidCName
, 'DynamicEx') in Pkg
.Pcds
or
3913 (VfrPcd
.TokenCName
, VfrPcd
.TokenSpaceGuidCName
, 'Dynamic') in Pkg
.Pcds
):
3917 ModuleType
= self
.ModuleType
3918 if ModuleType
== 'UEFI_DRIVER' and self
.DepexGenerated
:
3919 ModuleType
= 'DXE_DRIVER'
3922 if self
.PcdIsDriver
!= '':
3923 DriverType
= self
.PcdIsDriver
3926 MDefs
= self
.Module
.Defines
3929 'module_name' : self
.Name
,
3930 'module_guid' : Guid
,
3931 'module_module_type' : ModuleType
,
3932 'module_version_string' : [MDefs
['VERSION_STRING']] if 'VERSION_STRING' in MDefs
else [],
3933 'pcd_is_driver_string' : [],
3934 'module_uefi_specification_version' : [],
3935 'module_pi_specification_version' : [],
3936 'module_entry_point' : self
.Module
.ModuleEntryPointList
,
3937 'module_unload_image' : self
.Module
.ModuleUnloadImageList
,
3938 'module_constructor' : self
.Module
.ConstructorList
,
3939 'module_destructor' : self
.Module
.DestructorList
,
3940 'module_shadow' : [MDefs
['SHADOW']] if 'SHADOW' in MDefs
else [],
3941 'module_pci_vendor_id' : [MDefs
['PCI_VENDOR_ID']] if 'PCI_VENDOR_ID' in MDefs
else [],
3942 'module_pci_device_id' : [MDefs
['PCI_DEVICE_ID']] if 'PCI_DEVICE_ID' in MDefs
else [],
3943 'module_pci_class_code' : [MDefs
['PCI_CLASS_CODE']] if 'PCI_CLASS_CODE' in MDefs
else [],
3944 'module_pci_revision' : [MDefs
['PCI_REVISION']] if 'PCI_REVISION' in MDefs
else [],
3945 'module_build_number' : [MDefs
['BUILD_NUMBER']] if 'BUILD_NUMBER' in MDefs
else [],
3946 'module_spec' : [MDefs
['SPEC']] if 'SPEC' in MDefs
else [],
3947 'module_uefi_hii_resource_section' : [MDefs
['UEFI_HII_RESOURCE_SECTION']] if 'UEFI_HII_RESOURCE_SECTION' in MDefs
else [],
3948 'module_uni_file' : [MDefs
['MODULE_UNI_FILE']] if 'MODULE_UNI_FILE' in MDefs
else [],
3949 'module_arch' : self
.Arch
,
3950 'package_item' : ['%s' % (Package
.MetaFile
.File
.replace('\\', '/')) for Package
in Packages
],
3952 'patchablepcd_item' : [],
3954 'protocol_item' : [],
3958 'libraryclasses_item' : []
3961 if 'MODULE_UNI_FILE' in MDefs
:
3962 UNIFile
= os
.path
.join(self
.MetaFile
.Dir
, MDefs
['MODULE_UNI_FILE'])
3963 if os
.path
.isfile(UNIFile
):
3964 shutil
.copy2(UNIFile
, self
.OutputDir
)
3966 if self
.AutoGenVersion
> int(gInfSpecVersion
, 0):
3967 AsBuiltInfDict
['module_inf_version'] = '0x%08x' % self
.AutoGenVersion
3969 AsBuiltInfDict
['module_inf_version'] = gInfSpecVersion
3972 AsBuiltInfDict
['pcd_is_driver_string'] += [DriverType
]
3974 if 'UEFI_SPECIFICATION_VERSION' in self
.Specification
:
3975 AsBuiltInfDict
['module_uefi_specification_version'] += [self
.Specification
['UEFI_SPECIFICATION_VERSION']]
3976 if 'PI_SPECIFICATION_VERSION' in self
.Specification
:
3977 AsBuiltInfDict
['module_pi_specification_version'] += [self
.Specification
['PI_SPECIFICATION_VERSION']]
3979 OutputDir
= self
.OutputDir
.replace('\\', '/').strip('/')
3980 for Item
in self
.CodaTargetList
:
3981 File
= Item
.Target
.Path
.replace('\\', '/').strip('/').replace(OutputDir
, '').strip('/')
3982 if File
not in self
.OutputFile
:
3983 self
.OutputFile
.append(File
)
3984 if Item
.Target
.Ext
.lower() == '.aml':
3985 AsBuiltInfDict
['binary_item'] += ['ASL|' + File
]
3986 elif Item
.Target
.Ext
.lower() == '.acpi':
3987 AsBuiltInfDict
['binary_item'] += ['ACPI|' + File
]
3988 elif Item
.Target
.Ext
.lower() == '.efi':
3989 AsBuiltInfDict
['binary_item'] += ['PE32|' + self
.Name
+ '.efi']
3991 AsBuiltInfDict
['binary_item'] += ['BIN|' + File
]
3992 if self
.DepexGenerated
:
3993 if self
.Name
+ '.depex' not in self
.OutputFile
:
3994 self
.OutputFile
.append(self
.Name
+ '.depex')
3995 if self
.ModuleType
in ['PEIM']:
3996 AsBuiltInfDict
['binary_item'] += ['PEI_DEPEX|' + self
.Name
+ '.depex']
3997 if self
.ModuleType
in ['DXE_DRIVER', 'DXE_RUNTIME_DRIVER', 'DXE_SAL_DRIVER', 'UEFI_DRIVER']:
3998 AsBuiltInfDict
['binary_item'] += ['DXE_DEPEX|' + self
.Name
+ '.depex']
3999 if self
.ModuleType
in ['DXE_SMM_DRIVER']:
4000 AsBuiltInfDict
['binary_item'] += ['SMM_DEPEX|' + self
.Name
+ '.depex']
4002 Bin
= self
._GenOffsetBin
()
4004 AsBuiltInfDict
['binary_item'] += ['BIN|%s' % Bin
]
4005 if Bin
not in self
.OutputFile
:
4006 self
.OutputFile
.append(Bin
)
4008 for Root
, Dirs
, Files
in os
.walk(OutputDir
):
4010 if File
.lower().endswith('.pdb'):
4011 AsBuiltInfDict
['binary_item'] += ['DISPOSABLE|' + File
]
4012 if File
not in self
.OutputFile
:
4013 self
.OutputFile
.append(File
)
4014 HeaderComments
= self
.Module
.HeaderComments
4016 for Index
in range(len(HeaderComments
)):
4017 if HeaderComments
[Index
].find('@BinaryHeader') != -1:
4018 HeaderComments
[Index
] = HeaderComments
[Index
].replace('@BinaryHeader', '@file')
4021 AsBuiltInfDict
['header_comments'] = '\n'.join(HeaderComments
[StartPos
:]).replace(':#', '://')
4022 AsBuiltInfDict
['tail_comments'] = '\n'.join(self
.Module
.TailComments
)
4025 (self
.ProtocolList
, self
._ProtocolComments
, 'protocol_item'),
4026 (self
.PpiList
, self
._PpiComments
, 'ppi_item'),
4027 (GuidList
, self
._GuidComments
, 'guid_item')
4029 for Item
in GenList
:
4030 for CName
in Item
[0]:
4032 if CName
in Item
[1]:
4033 Comments
= '\n '.join(Item
[1][CName
])
4036 Entry
= Comments
+ '\n ' + CName
4037 AsBuiltInfDict
[Item
[2]].append(Entry
)
4038 PatchList
= parsePcdInfoFromMapFile(
4039 os
.path
.join(self
.OutputDir
, self
.Name
+ '.map'),
4040 os
.path
.join(self
.OutputDir
, self
.Name
+ '.efi')
4043 for Pcd
in PatchablePcds
:
4044 TokenCName
= Pcd
.TokenCName
4045 for PcdItem
in GlobalData
.MixedPcd
:
4046 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
4047 TokenCName
= PcdItem
[0]
4049 for PatchPcd
in PatchList
:
4050 if TokenCName
== PatchPcd
[0]:
4055 if Pcd
.DatumType
== 'BOOLEAN':
4056 BoolValue
= Pcd
.DefaultValue
.upper()
4057 if BoolValue
== 'TRUE':
4058 Pcd
.DefaultValue
= '1'
4059 elif BoolValue
== 'FALSE':
4060 Pcd
.DefaultValue
= '0'
4062 if Pcd
.DatumType
!= 'VOID*':
4063 HexFormat
= '0x%02x'
4064 if Pcd
.DatumType
== 'UINT16':
4065 HexFormat
= '0x%04x'
4066 elif Pcd
.DatumType
== 'UINT32':
4067 HexFormat
= '0x%08x'
4068 elif Pcd
.DatumType
== 'UINT64':
4069 HexFormat
= '0x%016x'
4070 PcdValue
= HexFormat
% int(Pcd
.DefaultValue
, 0)
4072 if Pcd
.MaxDatumSize
== None or Pcd
.MaxDatumSize
== '':
4073 EdkLogger
.error("build", AUTOGEN_ERROR
,
4074 "Unknown [MaxDatumSize] of PCD [%s.%s]" % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
4076 ArraySize
= int(Pcd
.MaxDatumSize
, 0)
4077 PcdValue
= Pcd
.DefaultValue
4078 if PcdValue
[0] != '{':
4080 if PcdValue
[0] == 'L':
4082 PcdValue
= PcdValue
.lstrip('L')
4083 PcdValue
= eval(PcdValue
)
4085 for Index
in range(0, len(PcdValue
)):
4087 CharVal
= ord(PcdValue
[Index
])
4088 NewValue
= NewValue
+ '0x%02x' % (CharVal
& 0x00FF) + ', ' \
4089 + '0x%02x' % (CharVal
>> 8) + ', '
4091 NewValue
= NewValue
+ '0x%02x' % (ord(PcdValue
[Index
]) % 0x100) + ', '
4094 Padding
= Padding
* 2
4095 ArraySize
= ArraySize
/ 2
4096 if ArraySize
< (len(PcdValue
) + 1):
4097 EdkLogger
.error("build", AUTOGEN_ERROR
,
4098 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
4100 if ArraySize
> len(PcdValue
) + 1:
4101 NewValue
= NewValue
+ Padding
* (ArraySize
- len(PcdValue
) - 1)
4102 PcdValue
= NewValue
+ Padding
.strip().rstrip(',') + '}'
4103 elif len(PcdValue
.split(',')) <= ArraySize
:
4104 PcdValue
= PcdValue
.rstrip('}') + ', 0x00' * (ArraySize
- len(PcdValue
.split(',')))
4107 EdkLogger
.error("build", AUTOGEN_ERROR
,
4108 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
4110 PcdItem
= '%s.%s|%s|0x%X' % \
4111 (Pcd
.TokenSpaceGuidCName
, TokenCName
, PcdValue
, PatchPcd
[1])
4113 if (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in self
._PcdComments
:
4114 PcdComments
= '\n '.join(self
._PcdComments
[Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
])
4116 PcdItem
= PcdComments
+ '\n ' + PcdItem
4117 AsBuiltInfDict
['patchablepcd_item'].append(PcdItem
)
4120 for Pcd
in Pcds
+ VfrPcds
:
4125 TokenCName
= Pcd
.TokenCName
4126 for PcdItem
in GlobalData
.MixedPcd
:
4127 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
4128 TokenCName
= PcdItem
[0]
4130 if Pcd
.Type
== TAB_PCDS_DYNAMIC_EX_HII
:
4131 for SkuName
in Pcd
.SkuInfoList
:
4132 SkuInfo
= Pcd
.SkuInfoList
[SkuName
]
4133 SkuId
= SkuInfo
.SkuId
4134 HiiInfo
= '## %s|%s|%s' % (SkuInfo
.VariableName
, SkuInfo
.VariableGuid
, SkuInfo
.VariableOffset
)
4138 # Don't generate duplicated HII PCD
4140 if (SkuId
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in HiiPcds
:
4143 HiiPcds
.append((SkuId
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
4144 if (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in self
._PcdComments
:
4145 PcdCommentList
= self
._PcdComments
[Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
][:]
4149 for Index
, Comment
in enumerate(PcdCommentList
):
4150 for Usage
in UsageList
:
4151 if Comment
.find(Usage
) != -1:
4155 if UsageIndex
!= -1:
4156 PcdCommentList
[UsageIndex
] = '## %s %s %s' % (UsageStr
, HiiInfo
, PcdCommentList
[UsageIndex
].replace(UsageStr
, ''))
4158 PcdCommentList
.append('## UNDEFINED ' + HiiInfo
)
4159 PcdComments
= '\n '.join(PcdCommentList
)
4160 PcdEntry
= Pcd
.TokenSpaceGuidCName
+ '.' + TokenCName
4162 PcdEntry
= PcdComments
+ '\n ' + PcdEntry
4163 AsBuiltInfDict
['pcd_item'] += [PcdEntry
]
4164 for Item
in self
.BuildOption
:
4165 if 'FLAGS' in self
.BuildOption
[Item
]:
4166 AsBuiltInfDict
['flags_item'] += ['%s:%s_%s_%s_%s_FLAGS = %s' % (self
.ToolChainFamily
, self
.BuildTarget
, self
.ToolChain
, self
.Arch
, Item
, self
.BuildOption
[Item
]['FLAGS'].strip())]
4168 # Generated LibraryClasses section in comments.
4169 for Library
in self
.LibraryAutoGenList
:
4170 AsBuiltInfDict
['libraryclasses_item'] += [Library
.MetaFile
.File
.replace('\\', '/')]
4172 # Generated UserExtensions TianoCore section.
4173 # All tianocore user extensions are copied.
4175 for TianoCore
in self
._GetTianoCoreUserExtensionList
():
4176 UserExtStr
+= '\n'.join(TianoCore
)
4177 ExtensionFile
= os
.path
.join(self
.MetaFile
.Dir
, TianoCore
[1])
4178 if os
.path
.isfile(ExtensionFile
):
4179 shutil
.copy2(ExtensionFile
, self
.OutputDir
)
4180 AsBuiltInfDict
['userextension_tianocore_item'] = UserExtStr
4182 # Generated depex expression section in comments.
4183 AsBuiltInfDict
['depexsection_item'] = ''
4184 DepexExpresion
= self
._GetDepexExpresionString
()
4186 AsBuiltInfDict
['depexsection_item'] = DepexExpresion
4188 AsBuiltInf
= TemplateString()
4189 AsBuiltInf
.Append(gAsBuiltInfHeaderString
.Replace(AsBuiltInfDict
))
4191 SaveFileOnChange(os
.path
.join(self
.OutputDir
, self
.Name
+ '.inf'), str(AsBuiltInf
), False)
4193 self
.IsAsBuiltInfCreated
= True
4194 if GlobalData
.gBinCacheDest
:
4195 self
.CopyModuleToCache()
4197 def CopyModuleToCache(self
):
4198 FileDir
= path
.join(GlobalData
.gBinCacheDest
, self
.Arch
, self
.SourceDir
, self
.MetaFile
.BaseName
)
4199 CreateDirectory (FileDir
)
4200 HashFile
= path
.join(self
.BuildDir
, self
.Name
+ '.hash')
4201 ModuleFile
= path
.join(self
.OutputDir
, self
.Name
+ '.inf')
4202 if os
.path
.exists(HashFile
):
4203 shutil
.copy2(HashFile
, FileDir
)
4204 if os
.path
.exists(ModuleFile
):
4205 shutil
.copy2(ModuleFile
, FileDir
)
4206 if not self
.OutputFile
:
4207 Ma
= self
.Workspace
.BuildDatabase
[PathClass(ModuleFile
), self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
4208 self
.OutputFile
= Ma
.Binaries
4210 for File
in self
.OutputFile
:
4212 if not os
.path
.isabs(File
):
4213 File
= os
.path
.join(self
.OutputDir
, File
)
4214 if os
.path
.exists(File
):
4215 shutil
.copy2(File
, FileDir
)
4217 def AttemptModuleCacheCopy(self
):
4218 if self
.IsBinaryModule
:
4220 FileDir
= path
.join(GlobalData
.gBinCacheSource
, self
.Arch
, self
.SourceDir
, self
.MetaFile
.BaseName
)
4221 HashFile
= path
.join(FileDir
, self
.Name
+ '.hash')
4222 if os
.path
.exists(HashFile
):
4223 f
= open(HashFile
, 'r')
4224 CacheHash
= f
.read()
4226 if GlobalData
.gModuleHash
[self
.Arch
][self
.Name
]:
4227 if CacheHash
== GlobalData
.gModuleHash
[self
.Arch
][self
.Name
]:
4228 for root
, dir, files
in os
.walk(FileDir
):
4230 if self
.Name
+ '.hash' in f
:
4231 shutil
.copy2(HashFile
, self
.BuildDir
)
4233 File
= path
.join(root
, f
)
4234 shutil
.copy2(File
, self
.OutputDir
)
4235 if self
.Name
== "PcdPeim" or self
.Name
== "PcdDxe":
4236 CreatePcdDatabaseCode(self
, TemplateString(), TemplateString())
4240 ## Create makefile for the module and its dependent libraries
4242 # @param CreateLibraryMakeFile Flag indicating if or not the makefiles of
4243 # dependent libraries will be created
4245 def CreateMakeFile(self
, CreateLibraryMakeFile
=True, GenFfsList
= []):
4246 # Ignore generating makefile when it is a binary module
4247 if self
.IsBinaryModule
:
4250 if self
.IsMakeFileCreated
:
4252 self
.GenFfsList
= GenFfsList
4253 if not self
.IsLibrary
and CreateLibraryMakeFile
:
4254 for LibraryAutoGen
in self
.LibraryAutoGenList
:
4255 LibraryAutoGen
.CreateMakeFile()
4260 if len(self
.CustomMakefile
) == 0:
4261 Makefile
= GenMake
.ModuleMakefile(self
)
4263 Makefile
= GenMake
.CustomMakefile(self
)
4264 if Makefile
.Generate():
4265 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated makefile for module %s [%s]" %
4266 (self
.Name
, self
.Arch
))
4268 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of makefile for module %s [%s]" %
4269 (self
.Name
, self
.Arch
))
4271 self
.CreateTimeStamp(Makefile
)
4272 self
.IsMakeFileCreated
= True
4274 def CopyBinaryFiles(self
):
4275 for File
in self
.Module
.Binaries
:
4277 DstPath
= os
.path
.join(self
.OutputDir
, os
.path
.basename(SrcPath
))
4278 CopyLongFilePath(SrcPath
, DstPath
)
4279 ## Create autogen code for the module and its dependent libraries
4281 # @param CreateLibraryCodeFile Flag indicating if or not the code of
4282 # dependent libraries will be created
4284 def CreateCodeFile(self
, CreateLibraryCodeFile
=True):
4285 if self
.IsCodeFileCreated
:
4288 # Need to generate PcdDatabase even PcdDriver is binarymodule
4289 if self
.IsBinaryModule
and self
.PcdIsDriver
!= '':
4290 CreatePcdDatabaseCode(self
, TemplateString(), TemplateString())
4292 if self
.IsBinaryModule
:
4294 self
.CopyBinaryFiles()
4297 if not self
.IsLibrary
and CreateLibraryCodeFile
:
4298 for LibraryAutoGen
in self
.LibraryAutoGenList
:
4299 LibraryAutoGen
.CreateCodeFile()
4305 IgoredAutoGenList
= []
4307 for File
in self
.AutoGenFileList
:
4308 if GenC
.Generate(File
.Path
, self
.AutoGenFileList
[File
], File
.IsBinary
):
4309 #Ignore Edk AutoGen.c
4310 if self
.AutoGenVersion
< 0x00010005 and File
.Name
== 'AutoGen.c':
4313 AutoGenList
.append(str(File
))
4315 IgoredAutoGenList
.append(str(File
))
4317 # Skip the following code for EDK I inf
4318 if self
.AutoGenVersion
< 0x00010005:
4321 for ModuleType
in self
.DepexList
:
4322 # Ignore empty [depex] section or [depex] section for "USER_DEFINED" module
4323 if len(self
.DepexList
[ModuleType
]) == 0 or ModuleType
== "USER_DEFINED":
4326 Dpx
= GenDepex
.DependencyExpression(self
.DepexList
[ModuleType
], ModuleType
, True)
4327 DpxFile
= gAutoGenDepexFileName
% {"module_name" : self
.Name
}
4329 if len(Dpx
.PostfixNotation
) <> 0:
4330 self
.DepexGenerated
= True
4332 if Dpx
.Generate(path
.join(self
.OutputDir
, DpxFile
)):
4333 AutoGenList
.append(str(DpxFile
))
4335 IgoredAutoGenList
.append(str(DpxFile
))
4337 if IgoredAutoGenList
== []:
4338 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] files for module %s [%s]" %
4339 (" ".join(AutoGenList
), self
.Name
, self
.Arch
))
4340 elif AutoGenList
== []:
4341 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of [%s] files for module %s [%s]" %
4342 (" ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
4344 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] (skipped %s) files for module %s [%s]" %
4345 (" ".join(AutoGenList
), " ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
4347 self
.IsCodeFileCreated
= True
4350 ## Summarize the ModuleAutoGen objects of all libraries used by this module
4351 def _GetLibraryAutoGenList(self
):
4352 if self
._LibraryAutoGenList
== None:
4353 self
._LibraryAutoGenList
= []
4354 for Library
in self
.DependentLibraryList
:
4361 self
.PlatformInfo
.MetaFile
4363 if La
not in self
._LibraryAutoGenList
:
4364 self
._LibraryAutoGenList
.append(La
)
4365 for Lib
in La
.CodaTargetList
:
4366 self
._ApplyBuildRule
(Lib
.Target
, TAB_UNKNOWN_FILE
)
4367 return self
._LibraryAutoGenList
4369 def GenModuleHash(self
):
4370 if self
.Arch
not in GlobalData
.gModuleHash
:
4371 GlobalData
.gModuleHash
[self
.Arch
] = {}
4373 # Add Platform level hash
4374 m
.update(GlobalData
.gPlatformHash
)
4375 # Add Package level hash
4376 if self
.DependentPackageList
:
4377 for Pkg
in self
.DependentPackageList
:
4378 if Pkg
.PackageName
in GlobalData
.gPackageHash
[self
.Arch
]:
4379 m
.update(GlobalData
.gPackageHash
[self
.Arch
][Pkg
.PackageName
])
4382 if self
.LibraryAutoGenList
:
4383 for Lib
in self
.LibraryAutoGenList
:
4384 if Lib
.Name
not in GlobalData
.gModuleHash
[self
.Arch
]:
4386 m
.update(GlobalData
.gModuleHash
[self
.Arch
][Lib
.Name
])
4389 f
= open(str(self
.MetaFile
), 'r')
4393 # Add Module's source files
4394 if self
.SourceFileList
:
4395 for File
in self
.SourceFileList
:
4396 f
= open(str(File
), 'r')
4401 ModuleHashFile
= path
.join(self
.BuildDir
, self
.Name
+ ".hash")
4402 if self
.Name
not in GlobalData
.gModuleHash
[self
.Arch
]:
4403 GlobalData
.gModuleHash
[self
.Arch
][self
.Name
] = m
.hexdigest()
4404 if GlobalData
.gBinCacheSource
:
4405 CacheValid
= self
.AttemptModuleCacheCopy()
4408 return SaveFileOnChange(ModuleHashFile
, m
.hexdigest(), True)
4410 ## Decide whether we can skip the ModuleAutoGen process
4411 def CanSkipbyHash(self
):
4412 if GlobalData
.gUseHashCache
:
4413 return not self
.GenModuleHash()
4415 ## Decide whether we can skip the ModuleAutoGen process
4416 # If any source file is newer than the module than we cannot skip
4419 if not os
.path
.exists(self
.GetTimeStampPath()):
4421 #last creation time of the module
4422 DstTimeStamp
= os
.stat(self
.GetTimeStampPath())[8]
4424 SrcTimeStamp
= self
.Workspace
._SrcTimeStamp
4425 if SrcTimeStamp
> DstTimeStamp
:
4428 with
open(self
.GetTimeStampPath(),'r') as f
:
4430 source
= source
.rstrip('\n')
4431 if not os
.path
.exists(source
):
4433 if source
not in ModuleAutoGen
.TimeDict
:
4434 ModuleAutoGen
.TimeDict
[source
] = os
.stat(source
)[8]
4435 if ModuleAutoGen
.TimeDict
[source
] > DstTimeStamp
:
4439 def GetTimeStampPath(self
):
4440 if self
._TimeStampPath
== None:
4441 self
._TimeStampPath
= os
.path
.join(self
.MakeFileDir
, 'AutoGenTimeStamp')
4442 return self
._TimeStampPath
4443 def CreateTimeStamp(self
, Makefile
):
4447 FileSet
.add (self
.MetaFile
.Path
)
4449 for SourceFile
in self
.Module
.Sources
:
4450 FileSet
.add (SourceFile
.Path
)
4452 for Lib
in self
.DependentLibraryList
:
4453 FileSet
.add (Lib
.MetaFile
.Path
)
4455 for f
in self
.AutoGenDepSet
:
4456 FileSet
.add (f
.Path
)
4458 if os
.path
.exists (self
.GetTimeStampPath()):
4459 os
.remove (self
.GetTimeStampPath())
4460 with
open(self
.GetTimeStampPath(), 'w+') as file:
4464 Module
= property(_GetModule
)
4465 Name
= property(_GetBaseName
)
4466 Guid
= property(_GetGuid
)
4467 Version
= property(_GetVersion
)
4468 ModuleType
= property(_GetModuleType
)
4469 ComponentType
= property(_GetComponentType
)
4470 BuildType
= property(_GetBuildType
)
4471 PcdIsDriver
= property(_GetPcdIsDriver
)
4472 AutoGenVersion
= property(_GetAutoGenVersion
)
4473 Macros
= property(_GetMacros
)
4474 Specification
= property(_GetSpecification
)
4476 IsLibrary
= property(_IsLibrary
)
4477 IsBinaryModule
= property(_IsBinaryModule
)
4478 BuildDir
= property(_GetBuildDir
)
4479 OutputDir
= property(_GetOutputDir
)
4480 FfsOutputDir
= property(_GetFfsOutputDir
)
4481 DebugDir
= property(_GetDebugDir
)
4482 MakeFileDir
= property(_GetMakeFileDir
)
4483 CustomMakefile
= property(_GetCustomMakefile
)
4485 IncludePathList
= property(_GetIncludePathList
)
4486 IncludePathLength
= property(_GetIncludePathLength
)
4487 AutoGenFileList
= property(_GetAutoGenFileList
)
4488 UnicodeFileList
= property(_GetUnicodeFileList
)
4489 VfrFileList
= property(_GetVfrFileList
)
4490 SourceFileList
= property(_GetSourceFileList
)
4491 BinaryFileList
= property(_GetBinaryFiles
) # FileType : [File List]
4492 Targets
= property(_GetTargets
)
4493 IntroTargetList
= property(_GetIntroTargetList
)
4494 CodaTargetList
= property(_GetFinalTargetList
)
4495 FileTypes
= property(_GetFileTypes
)
4496 BuildRules
= property(_GetBuildRules
)
4497 IdfFileList
= property(_GetIdfFileList
)
4499 DependentPackageList
= property(_GetDependentPackageList
)
4500 DependentLibraryList
= property(_GetLibraryList
)
4501 LibraryAutoGenList
= property(_GetLibraryAutoGenList
)
4502 DerivedPackageList
= property(_GetDerivedPackageList
)
4504 ModulePcdList
= property(_GetModulePcdList
)
4505 LibraryPcdList
= property(_GetLibraryPcdList
)
4506 GuidList
= property(_GetGuidList
)
4507 ProtocolList
= property(_GetProtocolList
)
4508 PpiList
= property(_GetPpiList
)
4509 DepexList
= property(_GetDepexTokenList
)
4510 DxsFile
= property(_GetDxsFile
)
4511 DepexExpressionList
= property(_GetDepexExpressionTokenList
)
4512 BuildOption
= property(_GetModuleBuildOption
)
4513 BuildOptionIncPathList
= property(_GetBuildOptionIncPathList
)
4514 BuildCommand
= property(_GetBuildCommand
)
4516 FixedAtBuildPcds
= property(_GetFixedAtBuildPcds
)
4518 # This acts like the main() function for the script, unless it is 'import'ed into another script.
4519 if __name__
== '__main__':