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
47 ## Regular expression for splitting Dependency Expression string into tokens
48 gDepexTokenPattern
= re
.compile("(\(|\)|\w+| \S+\.inf)")
51 # Match name = variable
53 gEfiVarStoreNamePattern
= re
.compile("\s*name\s*=\s*(\w+)")
55 # The format of guid in efivarstore statement likes following and must be correct:
56 # guid = {0xA04A27f4, 0xDF00, 0x4D42, {0xB5, 0x52, 0x39, 0x51, 0x13, 0x02, 0x11, 0x3D}}
58 gEfiVarStoreGuidPattern
= re
.compile("\s*guid\s*=\s*({.*?{.*?}\s*})")
60 ## Mapping Makefile type
61 gMakeTypeMap
= {"MSFT":"nmake", "GCC":"gmake"}
64 ## Build rule configuration file
65 gDefaultBuildRuleFile
= 'build_rule.txt'
67 ## Tools definition configuration file
68 gDefaultToolsDefFile
= 'tools_def.txt'
70 ## Build rule default version
71 AutoGenReqBuildRuleVerNum
= "0.1"
73 ## default file name for AutoGen
74 gAutoGenCodeFileName
= "AutoGen.c"
75 gAutoGenHeaderFileName
= "AutoGen.h"
76 gAutoGenStringFileName
= "%(module_name)sStrDefs.h"
77 gAutoGenStringFormFileName
= "%(module_name)sStrDefs.hpk"
78 gAutoGenDepexFileName
= "%(module_name)s.depex"
79 gAutoGenImageDefFileName
= "%(module_name)sImgDefs.h"
80 gAutoGenIdfFileName
= "%(module_name)sIdf.hpk"
81 gInfSpecVersion
= "0x00010017"
84 # Template string to generic AsBuilt INF
86 gAsBuiltInfHeaderString
= TemplateString("""${header_comments}
92 INF_VERSION = ${module_inf_version}
93 BASE_NAME = ${module_name}
94 FILE_GUID = ${module_guid}
95 MODULE_TYPE = ${module_module_type}${BEGIN}
96 VERSION_STRING = ${module_version_string}${END}${BEGIN}
97 PCD_IS_DRIVER = ${pcd_is_driver_string}${END}${BEGIN}
98 UEFI_SPECIFICATION_VERSION = ${module_uefi_specification_version}${END}${BEGIN}
99 PI_SPECIFICATION_VERSION = ${module_pi_specification_version}${END}${BEGIN}
100 ENTRY_POINT = ${module_entry_point}${END}${BEGIN}
101 UNLOAD_IMAGE = ${module_unload_image}${END}${BEGIN}
102 CONSTRUCTOR = ${module_constructor}${END}${BEGIN}
103 DESTRUCTOR = ${module_destructor}${END}${BEGIN}
104 SHADOW = ${module_shadow}${END}${BEGIN}
105 PCI_VENDOR_ID = ${module_pci_vendor_id}${END}${BEGIN}
106 PCI_DEVICE_ID = ${module_pci_device_id}${END}${BEGIN}
107 PCI_CLASS_CODE = ${module_pci_class_code}${END}${BEGIN}
108 PCI_REVISION = ${module_pci_revision}${END}${BEGIN}
109 BUILD_NUMBER = ${module_build_number}${END}${BEGIN}
110 SPEC = ${module_spec}${END}${BEGIN}
111 UEFI_HII_RESOURCE_SECTION = ${module_uefi_hii_resource_section}${END}${BEGIN}
112 MODULE_UNI_FILE = ${module_uni_file}${END}
114 [Packages.${module_arch}]${BEGIN}
115 ${package_item}${END}
117 [Binaries.${module_arch}]${BEGIN}
120 [PatchPcd.${module_arch}]${BEGIN}
124 [Protocols.${module_arch}]${BEGIN}
128 [Ppis.${module_arch}]${BEGIN}
132 [Guids.${module_arch}]${BEGIN}
136 [PcdEx.${module_arch}]${BEGIN}
140 [LibraryClasses.${module_arch}]
141 ## @LIB_INSTANCES${BEGIN}
142 # ${libraryclasses_item}${END}
148 [BuildOptions.${module_arch}]
150 ## ${flags_item}${END}
153 ## Base class for AutoGen
155 # This class just implements the cache mechanism of AutoGen objects.
157 class AutoGen(object):
158 # database to maintain the objects of xxxAutoGen
159 _CACHE_
= {} # (BuildTarget, ToolChain) : {ARCH : {platform file: AutoGen object}}}
163 # @param Class class object of real AutoGen class
164 # (WorkspaceAutoGen, ModuleAutoGen or PlatformAutoGen)
165 # @param Workspace Workspace directory or WorkspaceAutoGen object
166 # @param MetaFile The path of meta file
167 # @param Target Build target
168 # @param Toolchain Tool chain name
169 # @param Arch Target arch
170 # @param *args The specific class related parameters
171 # @param **kwargs The specific class related dict parameters
173 def __new__(Class
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
174 # check if the object has been created
175 Key
= (Target
, Toolchain
)
176 if Key
not in Class
._CACHE
_ or Arch
not in Class
._CACHE
_[Key
] \
177 or MetaFile
not in Class
._CACHE
_[Key
][Arch
]:
178 AutoGenObject
= super(AutoGen
, Class
).__new
__(Class
)
179 # call real constructor
180 if not AutoGenObject
._Init
(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
182 if Key
not in Class
._CACHE
_:
183 Class
._CACHE
_[Key
] = {}
184 if Arch
not in Class
._CACHE
_[Key
]:
185 Class
._CACHE
_[Key
][Arch
] = {}
186 Class
._CACHE
_[Key
][Arch
][MetaFile
] = AutoGenObject
188 AutoGenObject
= Class
._CACHE
_[Key
][Arch
][MetaFile
]
194 # The file path of platform file will be used to represent hash value of this object
196 # @retval int Hash value of the file path of platform file
199 return hash(self
.MetaFile
)
203 # The file path of platform file will be used to represent this object
205 # @retval string String of platform file path
208 return str(self
.MetaFile
)
211 def __eq__(self
, Other
):
212 return Other
and self
.MetaFile
== Other
214 ## Workspace AutoGen class
216 # This class is used mainly to control the whole platform build for different
217 # architecture. This class will generate top level makefile.
219 class WorkspaceAutoGen(AutoGen
):
220 ## Real constructor of WorkspaceAutoGen
222 # This method behaves the same as __init__ except that it needs explicit invoke
223 # (in super class's __new__ method)
225 # @param WorkspaceDir Root directory of workspace
226 # @param ActivePlatform Meta-file of active platform
227 # @param Target Build target
228 # @param Toolchain Tool chain name
229 # @param ArchList List of architecture of current build
230 # @param MetaFileDb Database containing meta-files
231 # @param BuildConfig Configuration of build
232 # @param ToolDefinition Tool chain definitions
233 # @param FlashDefinitionFile File of flash definition
234 # @param Fds FD list to be generated
235 # @param Fvs FV list to be generated
236 # @param Caps Capsule list to be generated
237 # @param SkuId SKU id from command line
239 def _Init(self
, WorkspaceDir
, ActivePlatform
, Target
, Toolchain
, ArchList
, MetaFileDb
,
240 BuildConfig
, ToolDefinition
, FlashDefinitionFile
='', Fds
=None, Fvs
=None, Caps
=None, SkuId
='', UniFlag
=None,
241 Progress
=None, BuildModule
=None):
248 self
.BuildDatabase
= MetaFileDb
249 self
.MetaFile
= ActivePlatform
250 self
.WorkspaceDir
= WorkspaceDir
251 self
.Platform
= self
.BuildDatabase
[self
.MetaFile
, 'COMMON', Target
, Toolchain
]
252 GlobalData
.gActivePlatform
= self
.Platform
253 self
.BuildTarget
= Target
254 self
.ToolChain
= Toolchain
255 self
.ArchList
= ArchList
257 self
.UniFlag
= UniFlag
259 self
.TargetTxt
= BuildConfig
260 self
.ToolDef
= ToolDefinition
261 self
.FdfFile
= FlashDefinitionFile
262 self
.FdTargetList
= Fds
263 self
.FvTargetList
= Fvs
264 self
.CapTargetList
= Caps
265 self
.AutoGenObjectList
= []
267 # there's many relative directory operations, so ...
268 os
.chdir(self
.WorkspaceDir
)
273 if not self
.ArchList
:
274 ArchList
= set(self
.Platform
.SupArchList
)
276 ArchList
= set(self
.ArchList
) & set(self
.Platform
.SupArchList
)
278 EdkLogger
.error("build", PARAMETER_INVALID
,
279 ExtraData
= "Invalid ARCH specified. [Valid ARCH: %s]" % (" ".join(self
.Platform
.SupArchList
)))
280 elif self
.ArchList
and len(ArchList
) != len(self
.ArchList
):
281 SkippedArchList
= set(self
.ArchList
).symmetric_difference(set(self
.Platform
.SupArchList
))
282 EdkLogger
.verbose("\nArch [%s] is ignored because the platform supports [%s] only!"
283 % (" ".join(SkippedArchList
), " ".join(self
.Platform
.SupArchList
)))
284 self
.ArchList
= tuple(ArchList
)
286 # Validate build target
287 if self
.BuildTarget
not in self
.Platform
.BuildTargets
:
288 EdkLogger
.error("build", PARAMETER_INVALID
,
289 ExtraData
="Build target [%s] is not supported by the platform. [Valid target: %s]"
290 % (self
.BuildTarget
, " ".join(self
.Platform
.BuildTargets
)))
293 # parse FDF file to get PCDs in it, if any
295 self
.FdfFile
= self
.Platform
.FlashDefinition
299 EdkLogger
.info('%-16s = %s' % ("Architecture(s)", ' '.join(self
.ArchList
)))
300 EdkLogger
.info('%-16s = %s' % ("Build target", self
.BuildTarget
))
301 EdkLogger
.info('%-16s = %s' % ("Toolchain", self
.ToolChain
))
303 EdkLogger
.info('\n%-24s = %s' % ("Active Platform", self
.Platform
))
305 EdkLogger
.info('%-24s = %s' % ("Active Module", BuildModule
))
308 EdkLogger
.info('%-24s = %s' % ("Flash Image Definition", self
.FdfFile
))
310 EdkLogger
.verbose("\nFLASH_DEFINITION = %s" % self
.FdfFile
)
313 Progress
.Start("\nProcessing meta-data")
317 # Mark now build in AutoGen Phase
319 GlobalData
.gAutoGenPhase
= True
320 Fdf
= FdfParser(self
.FdfFile
.Path
)
322 GlobalData
.gFdfParser
= Fdf
323 GlobalData
.gAutoGenPhase
= False
324 PcdSet
= Fdf
.Profile
.PcdDict
325 if Fdf
.CurrentFdName
and Fdf
.CurrentFdName
in Fdf
.Profile
.FdDict
:
326 FdDict
= Fdf
.Profile
.FdDict
[Fdf
.CurrentFdName
]
327 for FdRegion
in FdDict
.RegionList
:
328 if str(FdRegion
.RegionType
) is 'FILE' and self
.Platform
.VpdToolGuid
in str(FdRegion
.RegionDataList
):
329 if int(FdRegion
.Offset
) % 8 != 0:
330 EdkLogger
.error("build", FORMAT_INVALID
, 'The VPD Base Address %s must be 8-byte aligned.' % (FdRegion
.Offset
))
331 ModuleList
= Fdf
.Profile
.InfList
332 self
.FdfProfile
= Fdf
.Profile
333 for fvname
in self
.FvTargetList
:
334 if fvname
.upper() not in self
.FdfProfile
.FvDict
:
335 EdkLogger
.error("build", OPTION_VALUE_INVALID
,
336 "No such an FV in FDF file: %s" % fvname
)
338 # In DSC file may use FILE_GUID to override the module, then in the Platform.Modules use FILE_GUIDmodule.inf as key,
339 # but the path (self.MetaFile.Path) is the real path
340 for key
in self
.FdfProfile
.InfDict
:
344 for Arch
in self
.ArchList
:
345 Platform_cache
[Arch
] = self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
346 MetaFile_cache
[Arch
] = []
347 for Pkey
in Platform_cache
[Arch
].Modules
.keys():
348 MetaFile_cache
[Arch
].append(Platform_cache
[Arch
].Modules
[Pkey
].MetaFile
)
349 for Inf
in self
.FdfProfile
.InfDict
[key
]:
350 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
351 for Arch
in self
.ArchList
:
352 if ModuleFile
in MetaFile_cache
[Arch
]:
355 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, Target
, Toolchain
]
356 if not ModuleData
.IsBinaryModule
:
357 EdkLogger
.error('build', PARSER_ERROR
, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile
)
360 for Arch
in self
.ArchList
:
362 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
364 for Pkey
in Platform
.Modules
.keys():
365 MetaFileList
.append(Platform
.Modules
[Pkey
].MetaFile
)
366 for Inf
in self
.FdfProfile
.InfDict
[key
]:
367 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
368 if ModuleFile
in MetaFileList
:
370 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, Target
, Toolchain
]
371 if not ModuleData
.IsBinaryModule
:
372 EdkLogger
.error('build', PARSER_ERROR
, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile
)
377 self
.FdfProfile
= None
378 if self
.FdTargetList
:
379 EdkLogger
.info("No flash definition file found. FD [%s] will be ignored." % " ".join(self
.FdTargetList
))
380 self
.FdTargetList
= []
381 if self
.FvTargetList
:
382 EdkLogger
.info("No flash definition file found. FV [%s] will be ignored." % " ".join(self
.FvTargetList
))
383 self
.FvTargetList
= []
384 if self
.CapTargetList
:
385 EdkLogger
.info("No flash definition file found. Capsule [%s] will be ignored." % " ".join(self
.CapTargetList
))
386 self
.CapTargetList
= []
388 # apply SKU and inject PCDs from Flash Definition file
389 for Arch
in self
.ArchList
:
390 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
394 PGen
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
395 if GlobalData
.BuildOptionPcd
:
396 for i
, pcd
in enumerate(GlobalData
.BuildOptionPcd
):
397 if type(pcd
) is tuple:
399 (pcdname
, pcdvalue
) = pcd
.split('=')
401 EdkLogger
.error('build', AUTOGEN_ERROR
, "No Value specified for the PCD %s." % (pcdname
))
403 (TokenSpaceGuidCName
, TokenCName
) = pcdname
.split('.')
407 TokenSpaceGuidCName
= ''
408 HasTokenSpace
= False
409 TokenSpaceGuidCNameList
= []
413 for package
in PGen
.PackageList
:
414 for key
in package
.Pcds
:
415 PcdItem
= package
.Pcds
[key
]
417 if (PcdItem
.TokenCName
, PcdItem
.TokenSpaceGuidCName
) == (TokenCName
, TokenSpaceGuidCName
):
418 PcdDatumType
= PcdItem
.DatumType
419 NewValue
= BuildOptionPcdValueFormat(TokenSpaceGuidCName
, TokenCName
, PcdDatumType
, pcdvalue
)
422 if PcdItem
.TokenCName
== TokenCName
:
423 if not PcdItem
.TokenSpaceGuidCName
in TokenSpaceGuidCNameList
:
424 if len (TokenSpaceGuidCNameList
) < 1:
425 TokenSpaceGuidCNameList
.append(PcdItem
.TokenSpaceGuidCName
)
426 PcdDatumType
= PcdItem
.DatumType
427 TokenSpaceGuidCName
= PcdItem
.TokenSpaceGuidCName
428 NewValue
= BuildOptionPcdValueFormat(TokenSpaceGuidCName
, TokenCName
, PcdDatumType
, pcdvalue
)
434 "The Pcd %s is found under multiple different TokenSpaceGuid: %s and %s." % (TokenCName
, PcdItem
.TokenSpaceGuidCName
, TokenSpaceGuidCNameList
[0])
437 GlobalData
.BuildOptionPcd
[i
] = (TokenSpaceGuidCName
, TokenCName
, NewValue
)
441 EdkLogger
.error('build', AUTOGEN_ERROR
, "The Pcd %s.%s is not found in the DEC file." % (TokenSpaceGuidCName
, TokenCName
))
443 EdkLogger
.error('build', AUTOGEN_ERROR
, "The Pcd %s is not found in the DEC file." % (TokenCName
))
445 for BuildData
in PGen
.BuildDatabase
._CACHE
_.values():
446 if BuildData
.Arch
!= Arch
:
448 if BuildData
.MetaFile
.Ext
== '.dec':
450 for key
in BuildData
.Pcds
:
451 PcdItem
= BuildData
.Pcds
[key
]
452 if (TokenSpaceGuidCName
, TokenCName
) == (PcdItem
.TokenSpaceGuidCName
, PcdItem
.TokenCName
):
453 PcdItem
.DefaultValue
= NewValue
455 if (TokenCName
, TokenSpaceGuidCName
) in PcdSet
:
456 PcdSet
[(TokenCName
, TokenSpaceGuidCName
)] = NewValue
458 SourcePcdDict
= {'DynamicEx':[], 'PatchableInModule':[],'Dynamic':[],'FixedAtBuild':[]}
459 BinaryPcdDict
= {'DynamicEx':[], 'PatchableInModule':[]}
460 SourcePcdDict_Keys
= SourcePcdDict
.keys()
461 BinaryPcdDict_Keys
= BinaryPcdDict
.keys()
463 # generate the SourcePcdDict and BinaryPcdDict
464 for BuildData
in PGen
.BuildDatabase
._CACHE
_.values():
465 if BuildData
.Arch
!= Arch
:
467 if BuildData
.MetaFile
.Ext
== '.inf':
468 for key
in BuildData
.Pcds
:
469 if BuildData
.Pcds
[key
].Pending
:
470 if key
in Platform
.Pcds
:
471 PcdInPlatform
= Platform
.Pcds
[key
]
472 if PcdInPlatform
.Type
not in [None, '']:
473 BuildData
.Pcds
[key
].Type
= PcdInPlatform
.Type
475 if BuildData
.MetaFile
in Platform
.Modules
:
476 PlatformModule
= Platform
.Modules
[str(BuildData
.MetaFile
)]
477 if key
in PlatformModule
.Pcds
:
478 PcdInPlatform
= PlatformModule
.Pcds
[key
]
479 if PcdInPlatform
.Type
not in [None, '']:
480 BuildData
.Pcds
[key
].Type
= PcdInPlatform
.Type
482 if 'DynamicEx' in BuildData
.Pcds
[key
].Type
:
483 if BuildData
.IsBinaryModule
:
484 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) not in BinaryPcdDict
['DynamicEx']:
485 BinaryPcdDict
['DynamicEx'].append((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
487 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) not in SourcePcdDict
['DynamicEx']:
488 SourcePcdDict
['DynamicEx'].append((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
490 elif 'PatchableInModule' in BuildData
.Pcds
[key
].Type
:
491 if BuildData
.MetaFile
.Ext
== '.inf':
492 if BuildData
.IsBinaryModule
:
493 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) not in BinaryPcdDict
['PatchableInModule']:
494 BinaryPcdDict
['PatchableInModule'].append((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
496 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) not in SourcePcdDict
['PatchableInModule']:
497 SourcePcdDict
['PatchableInModule'].append((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
499 elif 'Dynamic' in BuildData
.Pcds
[key
].Type
:
500 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) not in SourcePcdDict
['Dynamic']:
501 SourcePcdDict
['Dynamic'].append((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
502 elif 'FixedAtBuild' in BuildData
.Pcds
[key
].Type
:
503 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) not in SourcePcdDict
['FixedAtBuild']:
504 SourcePcdDict
['FixedAtBuild'].append((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
508 # A PCD can only use one type for all source modules
510 for i
in SourcePcdDict_Keys
:
511 for j
in SourcePcdDict_Keys
:
513 IntersectionList
= list(set(SourcePcdDict
[i
]).intersection(set(SourcePcdDict
[j
])))
514 if len(IntersectionList
) > 0:
518 "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
),
519 ExtraData
="%s" % '\n\t'.join([str(P
[1]+'.'+P
[0]) for P
in IntersectionList
])
525 # intersection the BinaryPCD for Mixed PCD
527 for i
in BinaryPcdDict_Keys
:
528 for j
in BinaryPcdDict_Keys
:
530 IntersectionList
= list(set(BinaryPcdDict
[i
]).intersection(set(BinaryPcdDict
[j
])))
531 for item
in IntersectionList
:
532 NewPcd1
= (item
[0] + '_' + i
, item
[1])
533 NewPcd2
= (item
[0] + '_' + j
, item
[1])
534 if item
not in GlobalData
.MixedPcd
:
535 GlobalData
.MixedPcd
[item
] = [NewPcd1
, NewPcd2
]
537 if NewPcd1
not in GlobalData
.MixedPcd
[item
]:
538 GlobalData
.MixedPcd
[item
].append(NewPcd1
)
539 if NewPcd2
not in GlobalData
.MixedPcd
[item
]:
540 GlobalData
.MixedPcd
[item
].append(NewPcd2
)
545 # intersection the SourcePCD and BinaryPCD for Mixed PCD
547 for i
in SourcePcdDict_Keys
:
548 for j
in BinaryPcdDict_Keys
:
550 IntersectionList
= list(set(SourcePcdDict
[i
]).intersection(set(BinaryPcdDict
[j
])))
551 for item
in IntersectionList
:
552 NewPcd1
= (item
[0] + '_' + i
, item
[1])
553 NewPcd2
= (item
[0] + '_' + j
, item
[1])
554 if item
not in GlobalData
.MixedPcd
:
555 GlobalData
.MixedPcd
[item
] = [NewPcd1
, NewPcd2
]
557 if NewPcd1
not in GlobalData
.MixedPcd
[item
]:
558 GlobalData
.MixedPcd
[item
].append(NewPcd1
)
559 if NewPcd2
not in GlobalData
.MixedPcd
[item
]:
560 GlobalData
.MixedPcd
[item
].append(NewPcd2
)
564 for BuildData
in PGen
.BuildDatabase
._CACHE
_.values():
565 if BuildData
.Arch
!= Arch
:
567 for key
in BuildData
.Pcds
:
568 for SinglePcd
in GlobalData
.MixedPcd
:
569 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) == SinglePcd
:
570 for item
in GlobalData
.MixedPcd
[SinglePcd
]:
571 Pcd_Type
= item
[0].split('_')[-1]
572 if (Pcd_Type
== BuildData
.Pcds
[key
].Type
) or (Pcd_Type
== TAB_PCDS_DYNAMIC_EX
and BuildData
.Pcds
[key
].Type
in GenC
.gDynamicExPcd
) or \
573 (Pcd_Type
== TAB_PCDS_DYNAMIC
and BuildData
.Pcds
[key
].Type
in GenC
.gDynamicPcd
):
574 Value
= BuildData
.Pcds
[key
]
575 Value
.TokenCName
= BuildData
.Pcds
[key
].TokenCName
+ '_' + Pcd_Type
577 newkey
= (Value
.TokenCName
, key
[1])
579 newkey
= (Value
.TokenCName
, key
[1], key
[2])
580 del BuildData
.Pcds
[key
]
581 BuildData
.Pcds
[newkey
] = Value
589 # handle the mixed pcd in FDF file
591 if key
in GlobalData
.MixedPcd
:
594 for item
in GlobalData
.MixedPcd
[key
]:
597 #Collect package set information from INF of FDF
599 for Inf
in ModuleList
:
600 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
601 if ModuleFile
in Platform
.Modules
:
603 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, Target
, Toolchain
]
604 PkgSet
.update(ModuleData
.Packages
)
605 Pkgs
= list(PkgSet
) + list(PGen
.PackageList
)
608 DecPcds
[Pcd
[0], Pcd
[1]] = Pkg
.Pcds
[Pcd
]
609 DecPcdsKey
.add((Pcd
[0], Pcd
[1], Pcd
[2]))
611 Platform
.SkuName
= self
.SkuId
612 for Name
, Guid
in PcdSet
:
613 if (Name
, Guid
) not in DecPcds
:
617 "PCD (%s.%s) used in FDF is not declared in DEC files." % (Guid
, Name
),
618 File
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][0],
619 Line
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][1]
622 # Check whether Dynamic or DynamicEx PCD used in FDF file. If used, build break and give a error message.
623 if (Name
, Guid
, TAB_PCDS_FIXED_AT_BUILD
) in DecPcdsKey \
624 or (Name
, Guid
, TAB_PCDS_PATCHABLE_IN_MODULE
) in DecPcdsKey \
625 or (Name
, Guid
, TAB_PCDS_FEATURE_FLAG
) in DecPcdsKey
:
626 Platform
.AddPcd(Name
, Guid
, PcdSet
[Name
, Guid
])
628 elif (Name
, Guid
, TAB_PCDS_DYNAMIC
) in DecPcdsKey
or (Name
, Guid
, TAB_PCDS_DYNAMIC_EX
) in DecPcdsKey
:
632 "Using Dynamic or DynamicEx type of PCD [%s.%s] in FDF file is not allowed." % (Guid
, Name
),
633 File
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][0],
634 Line
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][1]
637 Pa
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
639 # Explicitly collect platform's dynamic PCDs
641 Pa
.CollectPlatformDynamicPcds()
642 Pa
.CollectFixedAtBuildPcds()
643 self
.AutoGenObjectList
.append(Pa
)
646 # Check PCDs token value conflict in each DEC file.
648 self
._CheckAllPcdsTokenValueConflict
()
651 # Check PCD type and definition between DSC and DEC
653 self
._CheckPcdDefineAndType
()
656 # self._CheckDuplicateInFV(Fdf)
658 self
._BuildDir
= None
660 self
._MakeFileDir
= None
661 self
._BuildCommand
= None
664 # Create BuildOptions Macro & PCD metafile, also add the Active Platform and FDF file.
666 content
= 'gCommandLineDefines: '
667 content
+= str(GlobalData
.gCommandLineDefines
)
668 content
+= os
.linesep
669 content
+= 'BuildOptionPcd: '
670 content
+= str(GlobalData
.BuildOptionPcd
)
671 content
+= os
.linesep
672 content
+= 'Active Platform: '
673 content
+= str(self
.Platform
)
674 content
+= os
.linesep
676 content
+= 'Flash Image Definition: '
677 content
+= str(self
.FdfFile
)
678 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'BuildOptions'), content
, False)
681 # Create PcdToken Number file for Dynamic/DynamicEx Pcd.
683 PcdTokenNumber
= 'PcdTokenNumber: '
684 if Pa
.PcdTokenNumber
:
685 if Pa
.DynamicPcdList
:
686 for Pcd
in Pa
.DynamicPcdList
:
687 PcdTokenNumber
+= os
.linesep
688 PcdTokenNumber
+= str((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
))
689 PcdTokenNumber
+= ' : '
690 PcdTokenNumber
+= str(Pa
.PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
])
691 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'PcdTokenNumber'), PcdTokenNumber
, False)
694 # Get set of workspace metafiles
696 AllWorkSpaceMetaFiles
= self
._GetMetaFiles
(Target
, Toolchain
, Arch
)
699 # Retrieve latest modified time of all metafiles
702 for f
in AllWorkSpaceMetaFiles
:
703 if os
.stat(f
)[8] > SrcTimeStamp
:
704 SrcTimeStamp
= os
.stat(f
)[8]
705 self
._SrcTimeStamp
= SrcTimeStamp
708 # Write metafile list to build directory
710 AutoGenFilePath
= os
.path
.join(self
.BuildDir
, 'AutoGen')
711 if os
.path
.exists (AutoGenFilePath
):
712 os
.remove(AutoGenFilePath
)
713 if not os
.path
.exists(self
.BuildDir
):
714 os
.makedirs(self
.BuildDir
)
715 with
open(os
.path
.join(self
.BuildDir
, 'AutoGen'), 'w+') as file:
716 for f
in AllWorkSpaceMetaFiles
:
721 def _GetMetaFiles(self
, Target
, Toolchain
, Arch
):
722 AllWorkSpaceMetaFiles
= set()
727 AllWorkSpaceMetaFiles
.add (self
.FdfFile
.Path
)
729 FdfFiles
= GlobalData
.gFdfParser
.GetAllIncludedFile()
731 AllWorkSpaceMetaFiles
.add (f
.FileName
)
735 AllWorkSpaceMetaFiles
.add(self
.MetaFile
.Path
)
738 # add build_rule.txt & tools_def.txt
740 AllWorkSpaceMetaFiles
.add(os
.path
.join(GlobalData
.gConfDirectory
, gDefaultBuildRuleFile
))
741 AllWorkSpaceMetaFiles
.add(os
.path
.join(GlobalData
.gConfDirectory
, gDefaultToolsDefFile
))
743 # add BuildOption metafile
745 AllWorkSpaceMetaFiles
.add(os
.path
.join(self
.BuildDir
, 'BuildOptions'))
747 # add PcdToken Number file for Dynamic/DynamicEx Pcd
749 AllWorkSpaceMetaFiles
.add(os
.path
.join(self
.BuildDir
, 'PcdTokenNumber'))
751 for Arch
in self
.ArchList
:
752 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
753 PGen
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
758 for Package
in PGen
.PackageList
:
759 AllWorkSpaceMetaFiles
.add(Package
.MetaFile
.Path
)
764 for filePath
in Platform
._RawData
.IncludedFiles
:
765 AllWorkSpaceMetaFiles
.add(filePath
.Path
)
767 return AllWorkSpaceMetaFiles
769 ## _CheckDuplicateInFV() method
771 # Check whether there is duplicate modules/files exist in FV section.
772 # The check base on the file GUID;
774 def _CheckDuplicateInFV(self
, Fdf
):
775 for Fv
in Fdf
.Profile
.FvDict
:
777 for FfsFile
in Fdf
.Profile
.FvDict
[Fv
].FfsList
:
778 if FfsFile
.InfFileName
and FfsFile
.NameGuid
== None:
783 for Pa
in self
.AutoGenObjectList
:
786 for Module
in Pa
.ModuleAutoGenList
:
787 if path
.normpath(Module
.MetaFile
.File
) == path
.normpath(FfsFile
.InfFileName
):
789 if not Module
.Guid
.upper() in _GuidDict
.keys():
790 _GuidDict
[Module
.Guid
.upper()] = FfsFile
793 EdkLogger
.error("build",
795 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile
.CurrentLineNum
,
796 FfsFile
.CurrentLineContent
,
797 _GuidDict
[Module
.Guid
.upper()].CurrentLineNum
,
798 _GuidDict
[Module
.Guid
.upper()].CurrentLineContent
,
799 Module
.Guid
.upper()),
800 ExtraData
=self
.FdfFile
)
802 # Some INF files not have entity in DSC file.
805 if FfsFile
.InfFileName
.find('$') == -1:
806 InfPath
= NormPath(FfsFile
.InfFileName
)
807 if not os
.path
.exists(InfPath
):
808 EdkLogger
.error('build', GENFDS_ERROR
, "Non-existant Module %s !" % (FfsFile
.InfFileName
))
810 PathClassObj
= PathClass(FfsFile
.InfFileName
, self
.WorkspaceDir
)
812 # Here we just need to get FILE_GUID from INF file, use 'COMMON' as ARCH attribute. and use
813 # BuildObject from one of AutoGenObjectList is enough.
815 InfObj
= self
.AutoGenObjectList
[0].BuildDatabase
.WorkspaceDb
.BuildObject
[PathClassObj
, 'COMMON', self
.BuildTarget
, self
.ToolChain
]
816 if not InfObj
.Guid
.upper() in _GuidDict
.keys():
817 _GuidDict
[InfObj
.Guid
.upper()] = FfsFile
819 EdkLogger
.error("build",
821 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile
.CurrentLineNum
,
822 FfsFile
.CurrentLineContent
,
823 _GuidDict
[InfObj
.Guid
.upper()].CurrentLineNum
,
824 _GuidDict
[InfObj
.Guid
.upper()].CurrentLineContent
,
825 InfObj
.Guid
.upper()),
826 ExtraData
=self
.FdfFile
)
829 if FfsFile
.NameGuid
!= None:
830 _CheckPCDAsGuidPattern
= re
.compile("^PCD\(.+\..+\)$")
833 # If the NameGuid reference a PCD name.
834 # The style must match: PCD(xxxx.yyy)
836 if _CheckPCDAsGuidPattern
.match(FfsFile
.NameGuid
):
838 # Replace the PCD value.
840 _PcdName
= FfsFile
.NameGuid
.lstrip("PCD(").rstrip(")")
842 for Pa
in self
.AutoGenObjectList
:
844 for PcdItem
in Pa
.AllPcdList
:
845 if (PcdItem
.TokenSpaceGuidCName
+ "." + PcdItem
.TokenCName
) == _PcdName
:
847 # First convert from CFormatGuid to GUID string
849 _PcdGuidString
= GuidStructureStringToGuidString(PcdItem
.DefaultValue
)
851 if not _PcdGuidString
:
853 # Then try Byte array.
855 _PcdGuidString
= GuidStructureByteArrayToGuidString(PcdItem
.DefaultValue
)
857 if not _PcdGuidString
:
859 # Not Byte array or CFormat GUID, raise error.
861 EdkLogger
.error("build",
863 "The format of PCD value is incorrect. PCD: %s , Value: %s\n" % (_PcdName
, PcdItem
.DefaultValue
),
864 ExtraData
=self
.FdfFile
)
866 if not _PcdGuidString
.upper() in _GuidDict
.keys():
867 _GuidDict
[_PcdGuidString
.upper()] = FfsFile
871 EdkLogger
.error("build",
873 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile
.CurrentLineNum
,
874 FfsFile
.CurrentLineContent
,
875 _GuidDict
[_PcdGuidString
.upper()].CurrentLineNum
,
876 _GuidDict
[_PcdGuidString
.upper()].CurrentLineContent
,
877 FfsFile
.NameGuid
.upper()),
878 ExtraData
=self
.FdfFile
)
880 if not FfsFile
.NameGuid
.upper() in _GuidDict
.keys():
881 _GuidDict
[FfsFile
.NameGuid
.upper()] = FfsFile
884 # Two raw file GUID conflict.
886 EdkLogger
.error("build",
888 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile
.CurrentLineNum
,
889 FfsFile
.CurrentLineContent
,
890 _GuidDict
[FfsFile
.NameGuid
.upper()].CurrentLineNum
,
891 _GuidDict
[FfsFile
.NameGuid
.upper()].CurrentLineContent
,
892 FfsFile
.NameGuid
.upper()),
893 ExtraData
=self
.FdfFile
)
896 def _CheckPcdDefineAndType(self
):
898 "FixedAtBuild", "PatchableInModule", "FeatureFlag",
899 "Dynamic", #"DynamicHii", "DynamicVpd",
900 "DynamicEx", # "DynamicExHii", "DynamicExVpd"
903 # This dict store PCDs which are not used by any modules with specified arches
905 for Pa
in self
.AutoGenObjectList
:
906 # Key of DSC's Pcds dictionary is PcdCName, TokenSpaceGuid
907 for Pcd
in Pa
.Platform
.Pcds
:
908 PcdType
= Pa
.Platform
.Pcds
[Pcd
].Type
910 # If no PCD type, this PCD comes from FDF
914 # Try to remove Hii and Vpd suffix
915 if PcdType
.startswith("DynamicEx"):
916 PcdType
= "DynamicEx"
917 elif PcdType
.startswith("Dynamic"):
920 for Package
in Pa
.PackageList
:
921 # Key of DEC's Pcds dictionary is PcdCName, TokenSpaceGuid, PcdType
922 if (Pcd
[0], Pcd
[1], PcdType
) in Package
.Pcds
:
924 for Type
in PcdTypeList
:
925 if (Pcd
[0], Pcd
[1], Type
) in Package
.Pcds
:
929 "Type [%s] of PCD [%s.%s] in DSC file doesn't match the type [%s] defined in DEC file." \
930 % (Pa
.Platform
.Pcds
[Pcd
].Type
, Pcd
[1], Pcd
[0], Type
),
935 UnusedPcd
.setdefault(Pcd
, []).append(Pa
.Arch
)
937 for Pcd
in UnusedPcd
:
940 "The PCD was not specified by any INF module in the platform for the given architecture.\n"
941 "\tPCD: [%s.%s]\n\tPlatform: [%s]\n\tArch: %s"
942 % (Pcd
[1], Pcd
[0], os
.path
.basename(str(self
.MetaFile
)), str(UnusedPcd
[Pcd
])),
947 return "%s [%s]" % (self
.MetaFile
, ", ".join(self
.ArchList
))
949 ## Return the directory to store FV files
951 if self
._FvDir
== None:
952 self
._FvDir
= path
.join(self
.BuildDir
, 'FV')
955 ## Return the directory to store all intermediate and final files built
956 def _GetBuildDir(self
):
957 return self
.AutoGenObjectList
[0].BuildDir
959 ## Return the build output directory platform specifies
960 def _GetOutputDir(self
):
961 return self
.Platform
.OutputDirectory
963 ## Return platform name
965 return self
.Platform
.PlatformName
967 ## Return meta-file GUID
969 return self
.Platform
.Guid
971 ## Return platform version
972 def _GetVersion(self
):
973 return self
.Platform
.Version
975 ## Return paths of tools
976 def _GetToolDefinition(self
):
977 return self
.AutoGenObjectList
[0].ToolDefinition
979 ## Return directory of platform makefile
981 # @retval string Makefile directory
983 def _GetMakeFileDir(self
):
984 if self
._MakeFileDir
== None:
985 self
._MakeFileDir
= self
.BuildDir
986 return self
._MakeFileDir
988 ## Return build command string
990 # @retval string Build command string
992 def _GetBuildCommand(self
):
993 if self
._BuildCommand
== None:
994 # BuildCommand should be all the same. So just get one from platform AutoGen
995 self
._BuildCommand
= self
.AutoGenObjectList
[0].BuildCommand
996 return self
._BuildCommand
998 ## Check the PCDs token value conflict in each DEC file.
1000 # Will cause build break and raise error message while two PCDs conflict.
1004 def _CheckAllPcdsTokenValueConflict(self
):
1005 for Pa
in self
.AutoGenObjectList
:
1006 for Package
in Pa
.PackageList
:
1007 PcdList
= Package
.Pcds
.values()
1008 PcdList
.sort(lambda x
, y
: cmp(int(x
.TokenValue
, 0), int(y
.TokenValue
, 0)))
1010 while (Count
< len(PcdList
) - 1) :
1011 Item
= PcdList
[Count
]
1012 ItemNext
= PcdList
[Count
+ 1]
1014 # Make sure in the same token space the TokenValue should be unique
1016 if (int(Item
.TokenValue
, 0) == int(ItemNext
.TokenValue
, 0)):
1017 SameTokenValuePcdList
= []
1018 SameTokenValuePcdList
.append(Item
)
1019 SameTokenValuePcdList
.append(ItemNext
)
1020 RemainPcdListLength
= len(PcdList
) - Count
- 2
1021 for ValueSameCount
in range(RemainPcdListLength
):
1022 if int(PcdList
[len(PcdList
) - RemainPcdListLength
+ ValueSameCount
].TokenValue
, 0) == int(Item
.TokenValue
, 0):
1023 SameTokenValuePcdList
.append(PcdList
[len(PcdList
) - RemainPcdListLength
+ ValueSameCount
])
1027 # Sort same token value PCD list with TokenGuid and TokenCName
1029 SameTokenValuePcdList
.sort(lambda x
, y
: cmp("%s.%s" % (x
.TokenSpaceGuidCName
, x
.TokenCName
), "%s.%s" % (y
.TokenSpaceGuidCName
, y
.TokenCName
)))
1030 SameTokenValuePcdListCount
= 0
1031 while (SameTokenValuePcdListCount
< len(SameTokenValuePcdList
) - 1):
1033 TemListItem
= SameTokenValuePcdList
[SameTokenValuePcdListCount
]
1034 TemListItemNext
= SameTokenValuePcdList
[SameTokenValuePcdListCount
+ 1]
1036 if (TemListItem
.TokenSpaceGuidCName
== TemListItemNext
.TokenSpaceGuidCName
) and (TemListItem
.TokenCName
!= TemListItemNext
.TokenCName
):
1037 for PcdItem
in GlobalData
.MixedPcd
:
1038 if (TemListItem
.TokenCName
, TemListItem
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
] or \
1039 (TemListItemNext
.TokenCName
, TemListItemNext
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
1045 "The TokenValue [%s] of PCD [%s.%s] is conflict with: [%s.%s] in %s"\
1046 % (TemListItem
.TokenValue
, TemListItem
.TokenSpaceGuidCName
, TemListItem
.TokenCName
, TemListItemNext
.TokenSpaceGuidCName
, TemListItemNext
.TokenCName
, Package
),
1049 SameTokenValuePcdListCount
+= 1
1050 Count
+= SameTokenValuePcdListCount
1053 PcdList
= Package
.Pcds
.values()
1054 PcdList
.sort(lambda x
, y
: cmp("%s.%s" % (x
.TokenSpaceGuidCName
, x
.TokenCName
), "%s.%s" % (y
.TokenSpaceGuidCName
, y
.TokenCName
)))
1056 while (Count
< len(PcdList
) - 1) :
1057 Item
= PcdList
[Count
]
1058 ItemNext
= PcdList
[Count
+ 1]
1060 # Check PCDs with same TokenSpaceGuidCName.TokenCName have same token value as well.
1062 if (Item
.TokenSpaceGuidCName
== ItemNext
.TokenSpaceGuidCName
) and (Item
.TokenCName
== ItemNext
.TokenCName
) and (int(Item
.TokenValue
, 0) != int(ItemNext
.TokenValue
, 0)):
1066 "The TokenValue [%s] of PCD [%s.%s] in %s defined in two places should be same as well."\
1067 % (Item
.TokenValue
, Item
.TokenSpaceGuidCName
, Item
.TokenCName
, Package
),
1071 ## Generate fds command
1072 def _GenFdsCommand(self
):
1073 return (GenMake
.TopLevelMakefile(self
)._TEMPLATE
_.Replace(GenMake
.TopLevelMakefile(self
)._TemplateDict
)).strip()
1075 ## Create makefile for the platform and modules in it
1077 # @param CreateDepsMakeFile Flag indicating if the makefile for
1078 # modules will be created as well
1080 def CreateMakeFile(self
, CreateDepsMakeFile
=False):
1081 if CreateDepsMakeFile
:
1082 for Pa
in self
.AutoGenObjectList
:
1083 Pa
.CreateMakeFile(CreateDepsMakeFile
)
1085 ## Create autogen code for platform and modules
1087 # Since there's no autogen code for platform, this method will do nothing
1088 # if CreateModuleCodeFile is set to False.
1090 # @param CreateDepsCodeFile Flag indicating if creating module's
1091 # autogen code file or not
1093 def CreateCodeFile(self
, CreateDepsCodeFile
=False):
1094 if not CreateDepsCodeFile
:
1096 for Pa
in self
.AutoGenObjectList
:
1097 Pa
.CreateCodeFile(CreateDepsCodeFile
)
1099 ## Create AsBuilt INF file the platform
1101 def CreateAsBuiltInf(self
):
1104 Name
= property(_GetName
)
1105 Guid
= property(_GetGuid
)
1106 Version
= property(_GetVersion
)
1107 OutputDir
= property(_GetOutputDir
)
1109 ToolDefinition
= property(_GetToolDefinition
) # toolcode : tool path
1111 BuildDir
= property(_GetBuildDir
)
1112 FvDir
= property(_GetFvDir
)
1113 MakeFileDir
= property(_GetMakeFileDir
)
1114 BuildCommand
= property(_GetBuildCommand
)
1115 GenFdsCommand
= property(_GenFdsCommand
)
1117 ## AutoGen class for platform
1119 # PlatformAutoGen class will process the original information in platform
1120 # file in order to generate makefile for platform.
1122 class PlatformAutoGen(AutoGen
):
1124 # Used to store all PCDs for both PEI and DXE phase, in order to generate
1125 # correct PCD database
1128 _NonDynaPcdList_
= []
1132 # The priority list while override build option
1134 PrioList
= {"0x11111" : 16, # TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE (Highest)
1135 "0x01111" : 15, # ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
1136 "0x10111" : 14, # TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE
1137 "0x00111" : 13, # ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE
1138 "0x11011" : 12, # TARGET_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
1139 "0x01011" : 11, # ******_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
1140 "0x10011" : 10, # TARGET_*********_****_COMMANDTYPE_ATTRIBUTE
1141 "0x00011" : 9, # ******_*********_****_COMMANDTYPE_ATTRIBUTE
1142 "0x11101" : 8, # TARGET_TOOLCHAIN_ARCH_***********_ATTRIBUTE
1143 "0x01101" : 7, # ******_TOOLCHAIN_ARCH_***********_ATTRIBUTE
1144 "0x10101" : 6, # TARGET_*********_ARCH_***********_ATTRIBUTE
1145 "0x00101" : 5, # ******_*********_ARCH_***********_ATTRIBUTE
1146 "0x11001" : 4, # TARGET_TOOLCHAIN_****_***********_ATTRIBUTE
1147 "0x01001" : 3, # ******_TOOLCHAIN_****_***********_ATTRIBUTE
1148 "0x10001" : 2, # TARGET_*********_****_***********_ATTRIBUTE
1149 "0x00001" : 1} # ******_*********_****_***********_ATTRIBUTE (Lowest)
1151 ## The real constructor of PlatformAutoGen
1153 # This method is not supposed to be called by users of PlatformAutoGen. It's
1154 # only used by factory method __new__() to do real initialization work for an
1155 # object of PlatformAutoGen
1157 # @param Workspace WorkspaceAutoGen object
1158 # @param PlatformFile Platform file (DSC file)
1159 # @param Target Build target (DEBUG, RELEASE)
1160 # @param Toolchain Name of tool chain
1161 # @param Arch arch of the platform supports
1163 def _Init(self
, Workspace
, PlatformFile
, Target
, Toolchain
, Arch
):
1164 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen platform [%s] [%s]" % (PlatformFile
, Arch
))
1165 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (PlatformFile
, Arch
, Toolchain
, Target
)
1167 self
.MetaFile
= PlatformFile
1168 self
.Workspace
= Workspace
1169 self
.WorkspaceDir
= Workspace
.WorkspaceDir
1170 self
.ToolChain
= Toolchain
1171 self
.BuildTarget
= Target
1173 self
.SourceDir
= PlatformFile
.SubDir
1174 self
.SourceOverrideDir
= None
1175 self
.FdTargetList
= self
.Workspace
.FdTargetList
1176 self
.FvTargetList
= self
.Workspace
.FvTargetList
1177 self
.AllPcdList
= []
1178 # get the original module/package/platform objects
1179 self
.BuildDatabase
= Workspace
.BuildDatabase
1181 # flag indicating if the makefile/C-code file has been created or not
1182 self
.IsMakeFileCreated
= False
1183 self
.IsCodeFileCreated
= False
1185 self
._Platform
= None
1188 self
._Version
= None
1190 self
._BuildRule
= None
1191 self
._SourceDir
= None
1192 self
._BuildDir
= None
1193 self
._OutputDir
= None
1195 self
._MakeFileDir
= None
1196 self
._FdfFile
= None
1198 self
._PcdTokenNumber
= None # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
1199 self
._DynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1200 self
._NonDynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1201 self
._NonDynamicPcdDict
= {}
1203 self
._ToolDefinitions
= None
1204 self
._ToolDefFile
= None # toolcode : tool path
1205 self
._ToolChainFamily
= None
1206 self
._BuildRuleFamily
= None
1207 self
._BuildOption
= None # toolcode : option
1208 self
._EdkBuildOption
= None # edktoolcode : option
1209 self
._EdkIIBuildOption
= None # edkiitoolcode : option
1210 self
._PackageList
= None
1211 self
._ModuleAutoGenList
= None
1212 self
._LibraryAutoGenList
= None
1213 self
._BuildCommand
= None
1214 self
._AsBuildInfList
= []
1215 self
._AsBuildModuleList
= []
1216 if GlobalData
.gFdfParser
!= None:
1217 self
._AsBuildInfList
= GlobalData
.gFdfParser
.Profile
.InfList
1218 for Inf
in self
._AsBuildInfList
:
1219 InfClass
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, self
.Arch
)
1220 M
= self
.BuildDatabase
[InfClass
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1221 if not M
.IsSupportedArch
:
1223 self
._AsBuildModuleList
.append(InfClass
)
1224 # get library/modules for build
1225 self
.LibraryBuildDirectoryList
= []
1226 self
.ModuleBuildDirectoryList
= []
1230 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
1232 ## Create autogen code for platform and modules
1234 # Since there's no autogen code for platform, this method will do nothing
1235 # if CreateModuleCodeFile is set to False.
1237 # @param CreateModuleCodeFile Flag indicating if creating module's
1238 # autogen code file or not
1240 def CreateCodeFile(self
, CreateModuleCodeFile
=False):
1241 # only module has code to be greated, so do nothing if CreateModuleCodeFile is False
1242 if self
.IsCodeFileCreated
or not CreateModuleCodeFile
:
1245 for Ma
in self
.ModuleAutoGenList
:
1246 Ma
.CreateCodeFile(True)
1248 # don't do this twice
1249 self
.IsCodeFileCreated
= True
1251 ## Generate Fds Command
1252 def _GenFdsCommand(self
):
1253 return self
.Workspace
.GenFdsCommand
1255 ## Create makefile for the platform and mdoules in it
1257 # @param CreateModuleMakeFile Flag indicating if the makefile for
1258 # modules will be created as well
1260 def CreateMakeFile(self
, CreateModuleMakeFile
=False):
1261 if CreateModuleMakeFile
:
1262 for ModuleFile
in self
.Platform
.Modules
:
1263 Ma
= ModuleAutoGen(self
.Workspace
, ModuleFile
, self
.BuildTarget
,
1264 self
.ToolChain
, self
.Arch
, self
.MetaFile
)
1265 Ma
.CreateMakeFile(True)
1266 #Ma.CreateAsBuiltInf()
1268 # no need to create makefile for the platform more than once
1269 if self
.IsMakeFileCreated
:
1272 # create library/module build dirs for platform
1273 Makefile
= GenMake
.PlatformMakefile(self
)
1274 self
.LibraryBuildDirectoryList
= Makefile
.GetLibraryBuildDirectoryList()
1275 self
.ModuleBuildDirectoryList
= Makefile
.GetModuleBuildDirectoryList()
1277 self
.IsMakeFileCreated
= True
1279 ## Deal with Shared FixedAtBuild Pcds
1281 def CollectFixedAtBuildPcds(self
):
1282 for LibAuto
in self
.LibraryAutoGenList
:
1283 FixedAtBuildPcds
= {}
1284 ShareFixedAtBuildPcdsSameValue
= {}
1285 for Module
in LibAuto
._ReferenceModules
:
1286 for Pcd
in Module
.FixedAtBuildPcds
+ LibAuto
.FixedAtBuildPcds
:
1287 key
= ".".join((Pcd
.TokenSpaceGuidCName
,Pcd
.TokenCName
))
1288 if key
not in FixedAtBuildPcds
:
1289 ShareFixedAtBuildPcdsSameValue
[key
] = True
1290 FixedAtBuildPcds
[key
] = Pcd
.DefaultValue
1292 if FixedAtBuildPcds
[key
] != Pcd
.DefaultValue
:
1293 ShareFixedAtBuildPcdsSameValue
[key
] = False
1294 for Pcd
in LibAuto
.FixedAtBuildPcds
:
1295 key
= ".".join((Pcd
.TokenSpaceGuidCName
,Pcd
.TokenCName
))
1296 if (Pcd
.TokenCName
,Pcd
.TokenSpaceGuidCName
) not in self
.NonDynamicPcdDict
:
1299 DscPcd
= self
.NonDynamicPcdDict
[(Pcd
.TokenCName
,Pcd
.TokenSpaceGuidCName
)]
1300 if DscPcd
.Type
!= "FixedAtBuild":
1302 if key
in ShareFixedAtBuildPcdsSameValue
and ShareFixedAtBuildPcdsSameValue
[key
]:
1303 LibAuto
.ConstPcd
[key
] = Pcd
.DefaultValue
1305 ## Collect dynamic PCDs
1307 # Gather dynamic PCDs list from each module and their settings from platform
1308 # This interface should be invoked explicitly when platform action is created.
1310 def CollectPlatformDynamicPcds(self
):
1311 # Override the platform Pcd's value by build option
1312 if GlobalData
.BuildOptionPcd
:
1313 for key
in self
.Platform
.Pcds
:
1314 PlatformPcd
= self
.Platform
.Pcds
[key
]
1315 for PcdItem
in GlobalData
.BuildOptionPcd
:
1316 if (PlatformPcd
.TokenSpaceGuidCName
, PlatformPcd
.TokenCName
) == (PcdItem
[0], PcdItem
[1]):
1317 PlatformPcd
.DefaultValue
= PcdItem
[2]
1318 if PlatformPcd
.SkuInfoList
:
1319 Sku
= PlatformPcd
.SkuInfoList
[PlatformPcd
.SkuInfoList
.keys()[0]]
1320 Sku
.DefaultValue
= PcdItem
[2]
1323 for key
in self
.Platform
.Pcds
:
1324 for SinglePcd
in GlobalData
.MixedPcd
:
1325 if (self
.Platform
.Pcds
[key
].TokenCName
, self
.Platform
.Pcds
[key
].TokenSpaceGuidCName
) == SinglePcd
:
1326 for item
in GlobalData
.MixedPcd
[SinglePcd
]:
1327 Pcd_Type
= item
[0].split('_')[-1]
1328 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 \
1329 (Pcd_Type
== TAB_PCDS_DYNAMIC
and self
.Platform
.Pcds
[key
].Type
in GenC
.gDynamicPcd
):
1330 Value
= self
.Platform
.Pcds
[key
]
1331 Value
.TokenCName
= self
.Platform
.Pcds
[key
].TokenCName
+ '_' + Pcd_Type
1333 newkey
= (Value
.TokenCName
, key
[1])
1335 newkey
= (Value
.TokenCName
, key
[1], key
[2])
1336 del self
.Platform
.Pcds
[key
]
1337 self
.Platform
.Pcds
[newkey
] = Value
1345 # for gathering error information
1346 NoDatumTypePcdList
= set()
1348 self
._GuidValue
= {}
1350 for InfName
in self
._AsBuildInfList
:
1351 InfName
= mws
.join(self
.WorkspaceDir
, InfName
)
1352 FdfModuleList
.append(os
.path
.normpath(InfName
))
1353 for F
in self
.Platform
.Modules
.keys():
1354 M
= ModuleAutoGen(self
.Workspace
, F
, self
.BuildTarget
, self
.ToolChain
, self
.Arch
, self
.MetaFile
)
1355 #GuidValue.update(M.Guids)
1357 self
.Platform
.Modules
[F
].M
= M
1359 for PcdFromModule
in M
.ModulePcdList
+ M
.LibraryPcdList
:
1360 # make sure that the "VOID*" kind of datum has MaxDatumSize set
1361 if PcdFromModule
.DatumType
== "VOID*" and PcdFromModule
.MaxDatumSize
in [None, '']:
1362 NoDatumTypePcdList
.add("%s.%s [%s]" % (PcdFromModule
.TokenSpaceGuidCName
, PcdFromModule
.TokenCName
, F
))
1364 # Check the PCD from Binary INF or Source INF
1365 if M
.IsBinaryModule
== True:
1366 PcdFromModule
.IsFromBinaryInf
= True
1368 # Check the PCD from DSC or not
1369 if (PcdFromModule
.TokenCName
, PcdFromModule
.TokenSpaceGuidCName
) in self
.Platform
.Pcds
.keys():
1370 PcdFromModule
.IsFromDsc
= True
1372 PcdFromModule
.IsFromDsc
= False
1373 if PcdFromModule
.Type
in GenC
.gDynamicPcd
or PcdFromModule
.Type
in GenC
.gDynamicExPcd
:
1374 if F
.Path
not in FdfModuleList
:
1375 # If one of the Source built modules listed in the DSC is not listed
1376 # in FDF modules, and the INF lists a PCD can only use the PcdsDynamic
1377 # access method (it is only listed in the DEC file that declares the
1378 # PCD as PcdsDynamic), then build tool will report warning message
1379 # notify the PI that they are attempting to build a module that must
1380 # be included in a flash image in order to be functional. These Dynamic
1381 # PCD will not be added into the Database unless it is used by other
1382 # modules that are included in the FDF file.
1383 if PcdFromModule
.Type
in GenC
.gDynamicPcd
and \
1384 PcdFromModule
.IsFromBinaryInf
== False:
1385 # Print warning message to let the developer make a determine.
1386 if PcdFromModule
not in PcdNotInDb
:
1387 PcdNotInDb
.append(PcdFromModule
)
1389 # If one of the Source built modules listed in the DSC is not listed in
1390 # FDF modules, and the INF lists a PCD can only use the PcdsDynamicEx
1391 # access method (it is only listed in the DEC file that declares the
1392 # PCD as PcdsDynamicEx), then DO NOT break the build; DO NOT add the
1393 # PCD to the Platform's PCD Database.
1394 if PcdFromModule
.Type
in GenC
.gDynamicExPcd
:
1395 if PcdFromModule
not in PcdNotInDb
:
1396 PcdNotInDb
.append(PcdFromModule
)
1399 # If a dynamic PCD used by a PEM module/PEI module & DXE module,
1400 # it should be stored in Pcd PEI database, If a dynamic only
1401 # used by DXE module, it should be stored in DXE PCD database.
1402 # The default Phase is DXE
1404 if M
.ModuleType
in ["PEIM", "PEI_CORE"]:
1405 PcdFromModule
.Phase
= "PEI"
1406 if PcdFromModule
not in self
._DynaPcdList
_:
1407 self
._DynaPcdList
_.append(PcdFromModule
)
1408 elif PcdFromModule
.Phase
== 'PEI':
1409 # overwrite any the same PCD existing, if Phase is PEI
1410 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1411 self
._DynaPcdList
_[Index
] = PcdFromModule
1412 elif PcdFromModule
not in self
._NonDynaPcdList
_:
1413 self
._NonDynaPcdList
_.append(PcdFromModule
)
1414 elif PcdFromModule
in self
._NonDynaPcdList
_ and PcdFromModule
.IsFromBinaryInf
== True:
1415 Index
= self
._NonDynaPcdList
_.index(PcdFromModule
)
1416 if self
._NonDynaPcdList
_[Index
].IsFromBinaryInf
== False:
1417 #The PCD from Binary INF will override the same one from source INF
1418 self
._NonDynaPcdList
_.remove (self
._NonDynaPcdList
_[Index
])
1419 PcdFromModule
.Pending
= False
1420 self
._NonDynaPcdList
_.append (PcdFromModule
)
1421 # Parse the DynamicEx PCD from the AsBuild INF module list of FDF.
1423 for ModuleInf
in self
.Platform
.Modules
.keys():
1424 DscModuleList
.append (os
.path
.normpath(ModuleInf
.Path
))
1425 # add the PCD from modules that listed in FDF but not in DSC to Database
1426 for InfName
in FdfModuleList
:
1427 if InfName
not in DscModuleList
:
1428 InfClass
= PathClass(InfName
)
1429 M
= self
.BuildDatabase
[InfClass
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1430 # If a module INF in FDF but not in current arch's DSC module list, it must be module (either binary or source)
1431 # for different Arch. PCDs in source module for different Arch is already added before, so skip the source module here.
1432 # For binary module, if in current arch, we need to list the PCDs into database.
1433 if not M
.IsSupportedArch
:
1435 # Override the module PCD setting by platform setting
1436 ModulePcdList
= self
.ApplyPcdSetting(M
, M
.Pcds
)
1437 for PcdFromModule
in ModulePcdList
:
1438 PcdFromModule
.IsFromBinaryInf
= True
1439 PcdFromModule
.IsFromDsc
= False
1440 # Only allow the DynamicEx and Patchable PCD in AsBuild INF
1441 if PcdFromModule
.Type
not in GenC
.gDynamicExPcd
and PcdFromModule
.Type
not in TAB_PCDS_PATCHABLE_IN_MODULE
:
1442 EdkLogger
.error("build", AUTOGEN_ERROR
, "PCD setting error",
1444 ExtraData
="\n\tExisted %s PCD %s in:\n\t\t%s\n"
1445 % (PcdFromModule
.Type
, PcdFromModule
.TokenCName
, InfName
))
1446 # make sure that the "VOID*" kind of datum has MaxDatumSize set
1447 if PcdFromModule
.DatumType
== "VOID*" and PcdFromModule
.MaxDatumSize
in [None, '']:
1448 NoDatumTypePcdList
.add("%s.%s [%s]" % (PcdFromModule
.TokenSpaceGuidCName
, PcdFromModule
.TokenCName
, InfName
))
1449 if M
.ModuleType
in ["PEIM", "PEI_CORE"]:
1450 PcdFromModule
.Phase
= "PEI"
1451 if PcdFromModule
not in self
._DynaPcdList
_ and PcdFromModule
.Type
in GenC
.gDynamicExPcd
:
1452 self
._DynaPcdList
_.append(PcdFromModule
)
1453 elif PcdFromModule
not in self
._NonDynaPcdList
_ and PcdFromModule
.Type
in TAB_PCDS_PATCHABLE_IN_MODULE
:
1454 self
._NonDynaPcdList
_.append(PcdFromModule
)
1455 if PcdFromModule
in self
._DynaPcdList
_ and PcdFromModule
.Phase
== 'PEI' and PcdFromModule
.Type
in GenC
.gDynamicExPcd
:
1456 # Overwrite the phase of any the same PCD existing, if Phase is PEI.
1457 # It is to solve the case that a dynamic PCD used by a PEM module/PEI
1458 # module & DXE module at a same time.
1459 # Overwrite the type of the PCDs in source INF by the type of AsBuild
1460 # INF file as DynamicEx.
1461 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1462 self
._DynaPcdList
_[Index
].Phase
= PcdFromModule
.Phase
1463 self
._DynaPcdList
_[Index
].Type
= PcdFromModule
.Type
1464 for PcdFromModule
in self
._NonDynaPcdList
_:
1465 # If a PCD is not listed in the DSC file, but binary INF files used by
1466 # this platform all (that use this PCD) list the PCD in a [PatchPcds]
1467 # section, AND all source INF files used by this platform the build
1468 # that use the PCD list the PCD in either a [Pcds] or [PatchPcds]
1469 # section, then the tools must NOT add the PCD to the Platform's PCD
1470 # Database; the build must assign the access method for this PCD as
1471 # PcdsPatchableInModule.
1472 if PcdFromModule
not in self
._DynaPcdList
_:
1474 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1475 if PcdFromModule
.IsFromDsc
== False and \
1476 PcdFromModule
.Type
in TAB_PCDS_PATCHABLE_IN_MODULE
and \
1477 PcdFromModule
.IsFromBinaryInf
== True and \
1478 self
._DynaPcdList
_[Index
].IsFromBinaryInf
== False:
1479 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1480 self
._DynaPcdList
_.remove (self
._DynaPcdList
_[Index
])
1482 # print out error information and break the build, if error found
1483 if len(NoDatumTypePcdList
) > 0:
1484 NoDatumTypePcdListString
= "\n\t\t".join(NoDatumTypePcdList
)
1485 EdkLogger
.error("build", AUTOGEN_ERROR
, "PCD setting error",
1487 ExtraData
="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"
1488 % NoDatumTypePcdListString
)
1489 self
._NonDynamicPcdList
= self
._NonDynaPcdList
_
1490 self
._DynamicPcdList
= self
._DynaPcdList
_
1492 # Sort dynamic PCD list to:
1493 # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should
1494 # try to be put header of dynamicd List
1495 # 2) If PCD is HII type, the PCD item should be put after unicode type PCD
1497 # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.
1499 UnicodePcdArray
= []
1503 VpdFile
= VpdInfoFile
.VpdInfoFile()
1504 NeedProcessVpdMapFile
= False
1506 for pcd
in self
.Platform
.Pcds
.keys():
1507 if pcd
not in self
._PlatformPcds
.keys():
1508 self
._PlatformPcds
[pcd
] = self
.Platform
.Pcds
[pcd
]
1510 if (self
.Workspace
.ArchList
[-1] == self
.Arch
):
1511 for Pcd
in self
._DynamicPcdList
:
1512 # just pick the a value to determine whether is unicode string type
1513 Sku
= Pcd
.SkuInfoList
[Pcd
.SkuInfoList
.keys()[0]]
1514 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1516 PcdValue
= Sku
.DefaultValue
1517 if Pcd
.DatumType
== 'VOID*' and PcdValue
.startswith("L"):
1518 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
1519 UnicodePcdArray
.append(Pcd
)
1520 elif len(Sku
.VariableName
) > 0:
1521 # if found HII type PCD then insert to right of UnicodeIndex
1522 HiiPcdArray
.append(Pcd
)
1524 OtherPcdArray
.append(Pcd
)
1525 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
1526 VpdPcdDict
[(Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
)] = Pcd
1528 PlatformPcds
= self
._PlatformPcds
.keys()
1531 # Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.
1533 for PcdKey
in PlatformPcds
:
1534 Pcd
= self
._PlatformPcds
[PcdKey
]
1535 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
] and \
1536 PcdKey
in VpdPcdDict
:
1537 Pcd
= VpdPcdDict
[PcdKey
]
1538 for (SkuName
,Sku
) in Pcd
.SkuInfoList
.items():
1539 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1540 PcdValue
= Sku
.DefaultValue
1542 PcdValue
= Pcd
.DefaultValue
1543 if Sku
.VpdOffset
!= '*':
1544 if PcdValue
.startswith("{"):
1546 elif PcdValue
.startswith("L"):
1551 VpdOffset
= int(Sku
.VpdOffset
)
1554 VpdOffset
= int(Sku
.VpdOffset
, 16)
1556 EdkLogger
.error("build", FORMAT_INVALID
, "Invalid offset value %s for PCD %s.%s." % (Sku
.VpdOffset
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
1557 if VpdOffset
% Alignment
!= 0:
1558 if PcdValue
.startswith("{"):
1559 EdkLogger
.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
), File
=self
.MetaFile
)
1561 EdkLogger
.error("build", FORMAT_INVALID
, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
, Alignment
))
1562 VpdFile
.Add(Pcd
, Sku
.VpdOffset
)
1563 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
1564 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== "*":
1565 NeedProcessVpdMapFile
= True
1566 if self
.Platform
.VpdToolGuid
== None or self
.Platform
.VpdToolGuid
== '':
1567 EdkLogger
.error("Build", FILE_NOT_FOUND
, \
1568 "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.")
1572 # Fix the PCDs define in VPD PCD section that never referenced by module.
1573 # An example is PCD for signature usage.
1575 for DscPcd
in PlatformPcds
:
1576 DscPcdEntry
= self
._PlatformPcds
[DscPcd
]
1577 if DscPcdEntry
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
1578 if not (self
.Platform
.VpdToolGuid
== None or self
.Platform
.VpdToolGuid
== ''):
1580 for VpdPcd
in VpdFile
._VpdArray
.keys():
1581 # This PCD has been referenced by module
1582 if (VpdPcd
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
1583 (VpdPcd
.TokenCName
== DscPcdEntry
.TokenCName
):
1586 # Not found, it should be signature
1588 # just pick the a value to determine whether is unicode string type
1589 for (SkuName
,Sku
) in DscPcdEntry
.SkuInfoList
.items():
1590 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1592 # Need to iterate DEC pcd information to get the value & datumtype
1593 for eachDec
in self
.PackageList
:
1594 for DecPcd
in eachDec
.Pcds
:
1595 DecPcdEntry
= eachDec
.Pcds
[DecPcd
]
1596 if (DecPcdEntry
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
1597 (DecPcdEntry
.TokenCName
== DscPcdEntry
.TokenCName
):
1598 # Print warning message to let the developer make a determine.
1599 EdkLogger
.warn("build", "Unreferenced vpd pcd used!",
1600 File
=self
.MetaFile
, \
1601 ExtraData
= "PCD: %s.%s used in the DSC file %s is unreferenced." \
1602 %(DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
, self
.Platform
.MetaFile
.Path
))
1604 DscPcdEntry
.DatumType
= DecPcdEntry
.DatumType
1605 DscPcdEntry
.DefaultValue
= DecPcdEntry
.DefaultValue
1606 DscPcdEntry
.TokenValue
= DecPcdEntry
.TokenValue
1607 DscPcdEntry
.TokenSpaceGuidValue
= eachDec
.Guids
[DecPcdEntry
.TokenSpaceGuidCName
]
1608 # Only fix the value while no value provided in DSC file.
1609 if (Sku
.DefaultValue
== "" or Sku
.DefaultValue
==None):
1610 DscPcdEntry
.SkuInfoList
[DscPcdEntry
.SkuInfoList
.keys()[0]].DefaultValue
= DecPcdEntry
.DefaultValue
1612 if DscPcdEntry
not in self
._DynamicPcdList
:
1613 self
._DynamicPcdList
.append(DscPcdEntry
)
1614 # Sku = DscPcdEntry.SkuInfoList[DscPcdEntry.SkuInfoList.keys()[0]]
1615 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1616 PcdValue
= Sku
.DefaultValue
1618 PcdValue
= DscPcdEntry
.DefaultValue
1619 if Sku
.VpdOffset
!= '*':
1620 if PcdValue
.startswith("{"):
1622 elif PcdValue
.startswith("L"):
1627 VpdOffset
= int(Sku
.VpdOffset
)
1630 VpdOffset
= int(Sku
.VpdOffset
, 16)
1632 EdkLogger
.error("build", FORMAT_INVALID
, "Invalid offset value %s for PCD %s.%s." % (Sku
.VpdOffset
, DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
))
1633 if VpdOffset
% Alignment
!= 0:
1634 if PcdValue
.startswith("{"):
1635 EdkLogger
.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
), File
=self
.MetaFile
)
1637 EdkLogger
.error("build", FORMAT_INVALID
, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
, Alignment
))
1638 VpdFile
.Add(DscPcdEntry
, Sku
.VpdOffset
)
1639 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== "*":
1640 NeedProcessVpdMapFile
= True
1641 if DscPcdEntry
.DatumType
== 'VOID*' and PcdValue
.startswith("L"):
1642 UnicodePcdArray
.append(DscPcdEntry
)
1643 elif len(Sku
.VariableName
) > 0:
1644 HiiPcdArray
.append(DscPcdEntry
)
1646 OtherPcdArray
.append(DscPcdEntry
)
1648 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
1652 if (self
.Platform
.FlashDefinition
== None or self
.Platform
.FlashDefinition
== '') and \
1653 VpdFile
.GetCount() != 0:
1654 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
,
1655 "Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD." % str(self
.Platform
.MetaFile
))
1657 if VpdFile
.GetCount() != 0:
1658 FvPath
= os
.path
.join(self
.BuildDir
, "FV")
1659 if not os
.path
.exists(FvPath
):
1663 EdkLogger
.error("build", FILE_WRITE_FAILURE
, "Fail to create FV folder under %s" % self
.BuildDir
)
1665 VpdFilePath
= os
.path
.join(FvPath
, "%s.txt" % self
.Platform
.VpdToolGuid
)
1667 if VpdFile
.Write(VpdFilePath
):
1668 # retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.
1670 for ToolDef
in self
.ToolDefinition
.values():
1671 if ToolDef
.has_key("GUID") and ToolDef
["GUID"] == self
.Platform
.VpdToolGuid
:
1672 if not ToolDef
.has_key("PATH"):
1673 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
, "PATH attribute was not provided for BPDG guid tool %s in tools_def.txt" % self
.Platform
.VpdToolGuid
)
1674 BPDGToolName
= ToolDef
["PATH"]
1676 # Call third party GUID BPDG tool.
1677 if BPDGToolName
!= None:
1678 VpdInfoFile
.CallExtenalBPDGTool(BPDGToolName
, VpdFilePath
)
1680 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.")
1682 # Process VPD map file generated by third party BPDG tool
1683 if NeedProcessVpdMapFile
:
1684 VpdMapFilePath
= os
.path
.join(self
.BuildDir
, "FV", "%s.map" % self
.Platform
.VpdToolGuid
)
1685 if os
.path
.exists(VpdMapFilePath
):
1686 VpdFile
.Read(VpdMapFilePath
)
1689 for Pcd
in self
._DynamicPcdList
:
1690 # just pick the a value to determine whether is unicode string type
1692 for (SkuName
,Sku
) in Pcd
.SkuInfoList
.items():
1693 if Sku
.VpdOffset
== "*":
1694 Sku
.VpdOffset
= VpdFile
.GetOffset(Pcd
)[i
].strip()
1697 EdkLogger
.error("build", FILE_READ_FAILURE
, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath
)
1699 # Delete the DynamicPcdList At the last time enter into this function
1700 del self
._DynamicPcdList
[:]
1701 self
._DynamicPcdList
.extend(UnicodePcdArray
)
1702 self
._DynamicPcdList
.extend(HiiPcdArray
)
1703 self
._DynamicPcdList
.extend(OtherPcdArray
)
1704 self
.AllPcdList
= self
._NonDynamicPcdList
+ self
._DynamicPcdList
1706 ## Return the platform build data object
1707 def _GetPlatform(self
):
1708 if self
._Platform
== None:
1709 self
._Platform
= self
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1710 return self
._Platform
1712 ## Return platform name
1714 return self
.Platform
.PlatformName
1716 ## Return the meta file GUID
1718 return self
.Platform
.Guid
1720 ## Return the platform version
1721 def _GetVersion(self
):
1722 return self
.Platform
.Version
1724 ## Return the FDF file name
1725 def _GetFdfFile(self
):
1726 if self
._FdfFile
== None:
1727 if self
.Workspace
.FdfFile
!= "":
1728 self
._FdfFile
= mws
.join(self
.WorkspaceDir
, self
.Workspace
.FdfFile
)
1731 return self
._FdfFile
1733 ## Return the build output directory platform specifies
1734 def _GetOutputDir(self
):
1735 return self
.Platform
.OutputDirectory
1737 ## Return the directory to store all intermediate and final files built
1738 def _GetBuildDir(self
):
1739 if self
._BuildDir
== None:
1740 if os
.path
.isabs(self
.OutputDir
):
1741 self
._BuildDir
= path
.join(
1742 path
.abspath(self
.OutputDir
),
1743 self
.BuildTarget
+ "_" + self
.ToolChain
,
1746 self
._BuildDir
= path
.join(
1749 self
.BuildTarget
+ "_" + self
.ToolChain
,
1751 return self
._BuildDir
1753 ## Return directory of platform makefile
1755 # @retval string Makefile directory
1757 def _GetMakeFileDir(self
):
1758 if self
._MakeFileDir
== None:
1759 self
._MakeFileDir
= path
.join(self
.BuildDir
, self
.Arch
)
1760 return self
._MakeFileDir
1762 ## Return build command string
1764 # @retval string Build command string
1766 def _GetBuildCommand(self
):
1767 if self
._BuildCommand
== None:
1768 self
._BuildCommand
= []
1769 if "MAKE" in self
.ToolDefinition
and "PATH" in self
.ToolDefinition
["MAKE"]:
1770 self
._BuildCommand
+= SplitOption(self
.ToolDefinition
["MAKE"]["PATH"])
1771 if "FLAGS" in self
.ToolDefinition
["MAKE"]:
1772 NewOption
= self
.ToolDefinition
["MAKE"]["FLAGS"].strip()
1774 self
._BuildCommand
+= SplitOption(NewOption
)
1775 return self
._BuildCommand
1777 ## Get tool chain definition
1779 # Get each tool defition for given tool chain from tools_def.txt and platform
1781 def _GetToolDefinition(self
):
1782 if self
._ToolDefinitions
== None:
1783 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDictionary
1784 if TAB_TOD_DEFINES_COMMAND_TYPE
not in self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
:
1785 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
, "No tools found in configuration",
1786 ExtraData
="[%s]" % self
.MetaFile
)
1787 self
._ToolDefinitions
= {}
1789 for Def
in ToolDefinition
:
1790 Target
, Tag
, Arch
, Tool
, Attr
= Def
.split("_")
1791 if Target
!= self
.BuildTarget
or Tag
!= self
.ToolChain
or Arch
!= self
.Arch
:
1794 Value
= ToolDefinition
[Def
]
1795 # don't record the DLL
1797 DllPathList
.add(Value
)
1800 if Tool
not in self
._ToolDefinitions
:
1801 self
._ToolDefinitions
[Tool
] = {}
1802 self
._ToolDefinitions
[Tool
][Attr
] = Value
1806 if GlobalData
.gOptions
.SilentMode
and "MAKE" in self
._ToolDefinitions
:
1807 if "FLAGS" not in self
._ToolDefinitions
["MAKE"]:
1808 self
._ToolDefinitions
["MAKE"]["FLAGS"] = ""
1809 self
._ToolDefinitions
["MAKE"]["FLAGS"] += " -s"
1811 for Tool
in self
._ToolDefinitions
:
1812 for Attr
in self
._ToolDefinitions
[Tool
]:
1813 Value
= self
._ToolDefinitions
[Tool
][Attr
]
1814 if Tool
in self
.BuildOption
and Attr
in self
.BuildOption
[Tool
]:
1815 # check if override is indicated
1816 if self
.BuildOption
[Tool
][Attr
].startswith('='):
1817 Value
= self
.BuildOption
[Tool
][Attr
][1:]
1820 Value
+= " " + self
.BuildOption
[Tool
][Attr
]
1822 Value
= self
.BuildOption
[Tool
][Attr
]
1825 # Don't put MAKE definition in the file
1829 ToolsDef
+= "%s = %s\n" % (Tool
, Value
)
1831 # Don't put MAKE definition in the file
1836 ToolsDef
+= "%s_%s = %s\n" % (Tool
, Attr
, Value
)
1839 SaveFileOnChange(self
.ToolDefinitionFile
, ToolsDef
)
1840 for DllPath
in DllPathList
:
1841 os
.environ
["PATH"] = DllPath
+ os
.pathsep
+ os
.environ
["PATH"]
1842 os
.environ
["MAKE_FLAGS"] = MakeFlags
1844 return self
._ToolDefinitions
1846 ## Return the paths of tools
1847 def _GetToolDefFile(self
):
1848 if self
._ToolDefFile
== None:
1849 self
._ToolDefFile
= os
.path
.join(self
.MakeFileDir
, "TOOLS_DEF." + self
.Arch
)
1850 return self
._ToolDefFile
1852 ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
1853 def _GetToolChainFamily(self
):
1854 if self
._ToolChainFamily
== None:
1855 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
1856 if TAB_TOD_DEFINES_FAMILY
not in ToolDefinition \
1857 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_FAMILY
] \
1858 or not ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]:
1859 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1861 self
._ToolChainFamily
= "MSFT"
1863 self
._ToolChainFamily
= ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]
1864 return self
._ToolChainFamily
1866 def _GetBuildRuleFamily(self
):
1867 if self
._BuildRuleFamily
== None:
1868 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
1869 if TAB_TOD_DEFINES_BUILDRULEFAMILY
not in ToolDefinition \
1870 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
] \
1871 or not ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]:
1872 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1874 self
._BuildRuleFamily
= "MSFT"
1876 self
._BuildRuleFamily
= ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]
1877 return self
._BuildRuleFamily
1879 ## Return the build options specific for all modules in this platform
1880 def _GetBuildOptions(self
):
1881 if self
._BuildOption
== None:
1882 self
._BuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
)
1883 return self
._BuildOption
1885 ## Return the build options specific for EDK modules in this platform
1886 def _GetEdkBuildOptions(self
):
1887 if self
._EdkBuildOption
== None:
1888 self
._EdkBuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDK_NAME
)
1889 return self
._EdkBuildOption
1891 ## Return the build options specific for EDKII modules in this platform
1892 def _GetEdkIIBuildOptions(self
):
1893 if self
._EdkIIBuildOption
== None:
1894 self
._EdkIIBuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDKII_NAME
)
1895 return self
._EdkIIBuildOption
1897 ## Parse build_rule.txt in Conf Directory.
1899 # @retval BuildRule object
1901 def _GetBuildRule(self
):
1902 if self
._BuildRule
== None:
1903 BuildRuleFile
= None
1904 if TAB_TAT_DEFINES_BUILD_RULE_CONF
in self
.Workspace
.TargetTxt
.TargetTxtDictionary
:
1905 BuildRuleFile
= self
.Workspace
.TargetTxt
.TargetTxtDictionary
[TAB_TAT_DEFINES_BUILD_RULE_CONF
]
1906 if BuildRuleFile
in [None, '']:
1907 BuildRuleFile
= gDefaultBuildRuleFile
1908 self
._BuildRule
= BuildRule(BuildRuleFile
)
1909 if self
._BuildRule
._FileVersion
== "":
1910 self
._BuildRule
._FileVersion
= AutoGenReqBuildRuleVerNum
1912 if self
._BuildRule
._FileVersion
< AutoGenReqBuildRuleVerNum
:
1913 # If Build Rule's version is less than the version number required by the tools, halting the build.
1914 EdkLogger
.error("build", AUTOGEN_ERROR
,
1915 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])"\
1916 % (self
._BuildRule
._FileVersion
, AutoGenReqBuildRuleVerNum
))
1918 return self
._BuildRule
1920 ## Summarize the packages used by modules in this platform
1921 def _GetPackageList(self
):
1922 if self
._PackageList
== None:
1923 self
._PackageList
= set()
1924 for La
in self
.LibraryAutoGenList
:
1925 self
._PackageList
.update(La
.DependentPackageList
)
1926 for Ma
in self
.ModuleAutoGenList
:
1927 self
._PackageList
.update(Ma
.DependentPackageList
)
1928 #Collect package set information from INF of FDF
1930 for ModuleFile
in self
._AsBuildModuleList
:
1931 if ModuleFile
in self
.Platform
.Modules
:
1933 ModuleData
= self
.BuildDatabase
[ModuleFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1934 PkgSet
.update(ModuleData
.Packages
)
1935 self
._PackageList
= list(self
._PackageList
) + list (PkgSet
)
1936 return self
._PackageList
1938 def _GetNonDynamicPcdDict(self
):
1939 if self
._NonDynamicPcdDict
:
1940 return self
._NonDynamicPcdDict
1941 for Pcd
in self
.NonDynamicPcdList
:
1942 self
._NonDynamicPcdDict
[(Pcd
.TokenCName
,Pcd
.TokenSpaceGuidCName
)] = Pcd
1943 return self
._NonDynamicPcdDict
1945 ## Get list of non-dynamic PCDs
1946 def _GetNonDynamicPcdList(self
):
1947 if self
._NonDynamicPcdList
== None:
1948 self
.CollectPlatformDynamicPcds()
1949 return self
._NonDynamicPcdList
1951 ## Get list of dynamic PCDs
1952 def _GetDynamicPcdList(self
):
1953 if self
._DynamicPcdList
== None:
1954 self
.CollectPlatformDynamicPcds()
1955 return self
._DynamicPcdList
1957 ## Generate Token Number for all PCD
1958 def _GetPcdTokenNumbers(self
):
1959 if self
._PcdTokenNumber
== None:
1960 self
._PcdTokenNumber
= sdict()
1963 # Make the Dynamic and DynamicEx PCD use within different TokenNumber area.
1967 # TokenNumber 0 ~ 10
1969 # TokeNumber 11 ~ 20
1971 for Pcd
in self
.DynamicPcdList
:
1972 if Pcd
.Phase
== "PEI":
1973 if Pcd
.Type
in ["Dynamic", "DynamicDefault", "DynamicVpd", "DynamicHii"]:
1974 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
1975 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1978 for Pcd
in self
.DynamicPcdList
:
1979 if Pcd
.Phase
== "PEI":
1980 if Pcd
.Type
in ["DynamicEx", "DynamicExDefault", "DynamicExVpd", "DynamicExHii"]:
1981 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
1982 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1985 for Pcd
in self
.DynamicPcdList
:
1986 if Pcd
.Phase
== "DXE":
1987 if Pcd
.Type
in ["Dynamic", "DynamicDefault", "DynamicVpd", "DynamicHii"]:
1988 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
1989 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1992 for Pcd
in self
.DynamicPcdList
:
1993 if Pcd
.Phase
== "DXE":
1994 if Pcd
.Type
in ["DynamicEx", "DynamicExDefault", "DynamicExVpd", "DynamicExHii"]:
1995 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
1996 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1999 for Pcd
in self
.NonDynamicPcdList
:
2000 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2002 return self
._PcdTokenNumber
2004 ## Summarize ModuleAutoGen objects of all modules/libraries to be built for this platform
2005 def _GetAutoGenObjectList(self
):
2006 self
._ModuleAutoGenList
= []
2007 self
._LibraryAutoGenList
= []
2008 for ModuleFile
in self
.Platform
.Modules
:
2017 if Ma
not in self
._ModuleAutoGenList
:
2018 self
._ModuleAutoGenList
.append(Ma
)
2019 for La
in Ma
.LibraryAutoGenList
:
2020 if La
not in self
._LibraryAutoGenList
:
2021 self
._LibraryAutoGenList
.append(La
)
2022 if Ma
not in La
._ReferenceModules
:
2023 La
._ReferenceModules
.append(Ma
)
2025 ## Summarize ModuleAutoGen objects of all modules to be built for this platform
2026 def _GetModuleAutoGenList(self
):
2027 if self
._ModuleAutoGenList
== None:
2028 self
._GetAutoGenObjectList
()
2029 return self
._ModuleAutoGenList
2031 ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
2032 def _GetLibraryAutoGenList(self
):
2033 if self
._LibraryAutoGenList
== None:
2034 self
._GetAutoGenObjectList
()
2035 return self
._LibraryAutoGenList
2037 ## Test if a module is supported by the platform
2039 # An error will be raised directly if the module or its arch is not supported
2040 # by the platform or current configuration
2042 def ValidModule(self
, Module
):
2043 return Module
in self
.Platform
.Modules
or Module
in self
.Platform
.LibraryInstances \
2044 or Module
in self
._AsBuildModuleList
2046 ## Resolve the library classes in a module to library instances
2048 # This method will not only resolve library classes but also sort the library
2049 # instances according to the dependency-ship.
2051 # @param Module The module from which the library classes will be resolved
2053 # @retval library_list List of library instances sorted
2055 def ApplyLibraryInstance(self
, Module
):
2056 # Cover the case that the binary INF file is list in the FDF file but not DSC file, return empty list directly
2057 if str(Module
) not in self
.Platform
.Modules
:
2060 ModuleType
= Module
.ModuleType
2062 # for overridding library instances with module specific setting
2063 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
2065 # add forced library instances (specified under LibraryClasses sections)
2067 # If a module has a MODULE_TYPE of USER_DEFINED,
2068 # do not link in NULL library class instances from the global [LibraryClasses.*] sections.
2070 if Module
.ModuleType
!= SUP_MODULE_USER_DEFINED
:
2071 for LibraryClass
in self
.Platform
.LibraryClasses
.GetKeys():
2072 if LibraryClass
.startswith("NULL") and self
.Platform
.LibraryClasses
[LibraryClass
, Module
.ModuleType
]:
2073 Module
.LibraryClasses
[LibraryClass
] = self
.Platform
.LibraryClasses
[LibraryClass
, Module
.ModuleType
]
2075 # add forced library instances (specified in module overrides)
2076 for LibraryClass
in PlatformModule
.LibraryClasses
:
2077 if LibraryClass
.startswith("NULL"):
2078 Module
.LibraryClasses
[LibraryClass
] = PlatformModule
.LibraryClasses
[LibraryClass
]
2081 LibraryConsumerList
= [Module
]
2083 ConsumedByList
= sdict()
2084 LibraryInstance
= sdict()
2086 EdkLogger
.verbose("")
2087 EdkLogger
.verbose("Library instances of module [%s] [%s]:" % (str(Module
), self
.Arch
))
2088 while len(LibraryConsumerList
) > 0:
2089 M
= LibraryConsumerList
.pop()
2090 for LibraryClassName
in M
.LibraryClasses
:
2091 if LibraryClassName
not in LibraryInstance
:
2092 # override library instance for this module
2093 if LibraryClassName
in PlatformModule
.LibraryClasses
:
2094 LibraryPath
= PlatformModule
.LibraryClasses
[LibraryClassName
]
2096 LibraryPath
= self
.Platform
.LibraryClasses
[LibraryClassName
, ModuleType
]
2097 if LibraryPath
== None or LibraryPath
== "":
2098 LibraryPath
= M
.LibraryClasses
[LibraryClassName
]
2099 if LibraryPath
== None or LibraryPath
== "":
2100 EdkLogger
.error("build", RESOURCE_NOT_AVAILABLE
,
2101 "Instance of library class [%s] is not found" % LibraryClassName
,
2103 ExtraData
="in [%s] [%s]\n\tconsumed by module [%s]" % (str(M
), self
.Arch
, str(Module
)))
2105 LibraryModule
= self
.BuildDatabase
[LibraryPath
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
2106 # for those forced library instance (NULL library), add a fake library class
2107 if LibraryClassName
.startswith("NULL"):
2108 LibraryModule
.LibraryClass
.append(LibraryClassObject(LibraryClassName
, [ModuleType
]))
2109 elif LibraryModule
.LibraryClass
== None \
2110 or len(LibraryModule
.LibraryClass
) == 0 \
2111 or (ModuleType
!= 'USER_DEFINED'
2112 and ModuleType
not in LibraryModule
.LibraryClass
[0].SupModList
):
2113 # only USER_DEFINED can link against any library instance despite of its SupModList
2114 EdkLogger
.error("build", OPTION_MISSING
,
2115 "Module type [%s] is not supported by library instance [%s]" \
2116 % (ModuleType
, LibraryPath
), File
=self
.MetaFile
,
2117 ExtraData
="consumed by [%s]" % str(Module
))
2119 LibraryInstance
[LibraryClassName
] = LibraryModule
2120 LibraryConsumerList
.append(LibraryModule
)
2121 EdkLogger
.verbose("\t" + str(LibraryClassName
) + " : " + str(LibraryModule
))
2123 LibraryModule
= LibraryInstance
[LibraryClassName
]
2125 if LibraryModule
== None:
2128 if LibraryModule
.ConstructorList
!= [] and LibraryModule
not in Constructor
:
2129 Constructor
.append(LibraryModule
)
2131 if LibraryModule
not in ConsumedByList
:
2132 ConsumedByList
[LibraryModule
] = []
2133 # don't add current module itself to consumer list
2135 if M
in ConsumedByList
[LibraryModule
]:
2137 ConsumedByList
[LibraryModule
].append(M
)
2139 # Initialize the sorted output list to the empty set
2141 SortedLibraryList
= []
2143 # Q <- Set of all nodes with no incoming edges
2145 LibraryList
= [] #LibraryInstance.values()
2147 for LibraryClassName
in LibraryInstance
:
2148 M
= LibraryInstance
[LibraryClassName
]
2149 LibraryList
.append(M
)
2150 if ConsumedByList
[M
] == []:
2154 # start the DAG algorithm
2158 while Q
== [] and EdgeRemoved
:
2160 # for each node Item with a Constructor
2161 for Item
in LibraryList
:
2162 if Item
not in Constructor
:
2164 # for each Node without a constructor with an edge e from Item to Node
2165 for Node
in ConsumedByList
[Item
]:
2166 if Node
in Constructor
:
2168 # remove edge e from the graph if Node has no constructor
2169 ConsumedByList
[Item
].remove(Node
)
2171 if ConsumedByList
[Item
] == []:
2172 # insert Item into Q
2177 # DAG is done if there's no more incoming edge for all nodes
2181 # remove node from Q
2184 SortedLibraryList
.append(Node
)
2186 # for each node Item with an edge e from Node to Item do
2187 for Item
in LibraryList
:
2188 if Node
not in ConsumedByList
[Item
]:
2190 # remove edge e from the graph
2191 ConsumedByList
[Item
].remove(Node
)
2193 if ConsumedByList
[Item
] != []:
2195 # insert Item into Q, if Item has no other incoming edges
2199 # if any remaining node Item in the graph has a constructor and an incoming edge, then the graph has a cycle
2201 for Item
in LibraryList
:
2202 if ConsumedByList
[Item
] != [] and Item
in Constructor
and len(Constructor
) > 1:
2203 ErrorMessage
= "\tconsumed by " + "\n\tconsumed by ".join([str(L
) for L
in ConsumedByList
[Item
]])
2204 EdkLogger
.error("build", BUILD_ERROR
, 'Library [%s] with constructors has a cycle' % str(Item
),
2205 ExtraData
=ErrorMessage
, File
=self
.MetaFile
)
2206 if Item
not in SortedLibraryList
:
2207 SortedLibraryList
.append(Item
)
2210 # Build the list of constructor and destructir names
2211 # The DAG Topo sort produces the destructor order, so the list of constructors must generated in the reverse order
2213 SortedLibraryList
.reverse()
2214 return SortedLibraryList
2217 ## Override PCD setting (type, value, ...)
2219 # @param ToPcd The PCD to be overrided
2220 # @param FromPcd The PCD overrideing from
2222 def _OverridePcd(self
, ToPcd
, FromPcd
, Module
=""):
2224 # in case there's PCDs coming from FDF file, which have no type given.
2225 # at this point, ToPcd.Type has the type found from dependent
2228 TokenCName
= ToPcd
.TokenCName
2229 for PcdItem
in GlobalData
.MixedPcd
:
2230 if (ToPcd
.TokenCName
, ToPcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
2231 TokenCName
= PcdItem
[0]
2234 if GlobalData
.BuildOptionPcd
:
2235 for pcd
in GlobalData
.BuildOptionPcd
:
2236 if (FromPcd
.TokenSpaceGuidCName
, FromPcd
.TokenCName
) == (pcd
[0], pcd
[1]):
2237 FromPcd
.DefaultValue
= pcd
[2]
2239 if ToPcd
.Pending
and FromPcd
.Type
not in [None, '']:
2240 ToPcd
.Type
= FromPcd
.Type
2241 elif (ToPcd
.Type
not in [None, '']) and (FromPcd
.Type
not in [None, ''])\
2242 and (ToPcd
.Type
!= FromPcd
.Type
) and (ToPcd
.Type
in FromPcd
.Type
):
2243 if ToPcd
.Type
.strip() == "DynamicEx":
2244 ToPcd
.Type
= FromPcd
.Type
2245 elif ToPcd
.Type
not in [None, ''] and FromPcd
.Type
not in [None, ''] \
2246 and ToPcd
.Type
!= FromPcd
.Type
:
2247 EdkLogger
.error("build", OPTION_CONFLICT
, "Mismatched PCD type",
2248 ExtraData
="%s.%s is defined as [%s] in module %s, but as [%s] in platform."\
2249 % (ToPcd
.TokenSpaceGuidCName
, TokenCName
,
2250 ToPcd
.Type
, Module
, FromPcd
.Type
),
2253 if FromPcd
.MaxDatumSize
not in [None, '']:
2254 ToPcd
.MaxDatumSize
= FromPcd
.MaxDatumSize
2255 if FromPcd
.DefaultValue
not in [None, '']:
2256 ToPcd
.DefaultValue
= FromPcd
.DefaultValue
2257 if FromPcd
.TokenValue
not in [None, '']:
2258 ToPcd
.TokenValue
= FromPcd
.TokenValue
2259 if FromPcd
.MaxDatumSize
not in [None, '']:
2260 ToPcd
.MaxDatumSize
= FromPcd
.MaxDatumSize
2261 if FromPcd
.DatumType
not in [None, '']:
2262 ToPcd
.DatumType
= FromPcd
.DatumType
2263 if FromPcd
.SkuInfoList
not in [None, '', []]:
2264 ToPcd
.SkuInfoList
= FromPcd
.SkuInfoList
2266 # check the validation of datum
2267 IsValid
, Cause
= CheckPcdDatum(ToPcd
.DatumType
, ToPcd
.DefaultValue
)
2269 EdkLogger
.error('build', FORMAT_INVALID
, Cause
, File
=self
.MetaFile
,
2270 ExtraData
="%s.%s" % (ToPcd
.TokenSpaceGuidCName
, TokenCName
))
2271 ToPcd
.validateranges
= FromPcd
.validateranges
2272 ToPcd
.validlists
= FromPcd
.validlists
2273 ToPcd
.expressions
= FromPcd
.expressions
2275 if ToPcd
.DatumType
== "VOID*" and ToPcd
.MaxDatumSize
in ['', None]:
2276 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "No MaxDatumSize specified for PCD %s.%s" \
2277 % (ToPcd
.TokenSpaceGuidCName
, TokenCName
))
2278 Value
= ToPcd
.DefaultValue
2279 if Value
in [None, '']:
2280 ToPcd
.MaxDatumSize
= '1'
2281 elif Value
[0] == 'L':
2282 ToPcd
.MaxDatumSize
= str((len(Value
) - 2) * 2)
2283 elif Value
[0] == '{':
2284 ToPcd
.MaxDatumSize
= str(len(Value
.split(',')))
2286 ToPcd
.MaxDatumSize
= str(len(Value
) - 1)
2288 # apply default SKU for dynamic PCDS if specified one is not available
2289 if (ToPcd
.Type
in PCD_DYNAMIC_TYPE_LIST
or ToPcd
.Type
in PCD_DYNAMIC_EX_TYPE_LIST
) \
2290 and ToPcd
.SkuInfoList
in [None, {}, '']:
2291 if self
.Platform
.SkuName
in self
.Platform
.SkuIds
:
2292 SkuName
= self
.Platform
.SkuName
2295 ToPcd
.SkuInfoList
= {
2296 SkuName
: SkuInfoClass(SkuName
, self
.Platform
.SkuIds
[SkuName
], '', '', '', '', '', ToPcd
.DefaultValue
)
2299 ## Apply PCD setting defined platform to a module
2301 # @param Module The module from which the PCD setting will be overrided
2303 # @retval PCD_list The list PCDs with settings from platform
2305 def ApplyPcdSetting(self
, Module
, Pcds
):
2306 # for each PCD in module
2307 for Name
, Guid
in Pcds
:
2308 PcdInModule
= Pcds
[Name
, Guid
]
2309 # find out the PCD setting in platform
2310 if (Name
, Guid
) in self
.Platform
.Pcds
:
2311 PcdInPlatform
= self
.Platform
.Pcds
[Name
, Guid
]
2313 PcdInPlatform
= None
2314 # then override the settings if any
2315 self
._OverridePcd
(PcdInModule
, PcdInPlatform
, Module
)
2316 # resolve the VariableGuid value
2317 for SkuId
in PcdInModule
.SkuInfoList
:
2318 Sku
= PcdInModule
.SkuInfoList
[SkuId
]
2319 if Sku
.VariableGuid
== '': continue
2320 Sku
.VariableGuidValue
= GuidValue(Sku
.VariableGuid
, self
.PackageList
, self
.MetaFile
.Path
)
2321 if Sku
.VariableGuidValue
== None:
2322 PackageList
= "\n\t".join([str(P
) for P
in self
.PackageList
])
2325 RESOURCE_NOT_AVAILABLE
,
2326 "Value of GUID [%s] is not found in" % Sku
.VariableGuid
,
2327 ExtraData
=PackageList
+ "\n\t(used with %s.%s from module %s)" \
2328 % (Guid
, Name
, str(Module
)),
2332 # override PCD settings with module specific setting
2333 if Module
in self
.Platform
.Modules
:
2334 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
2335 for Key
in PlatformModule
.Pcds
:
2337 self
._OverridePcd
(Pcds
[Key
], PlatformModule
.Pcds
[Key
], Module
)
2338 return Pcds
.values()
2340 ## Resolve library names to library modules
2342 # (for Edk.x modules)
2344 # @param Module The module from which the library names will be resolved
2346 # @retval library_list The list of library modules
2348 def ResolveLibraryReference(self
, Module
):
2349 EdkLogger
.verbose("")
2350 EdkLogger
.verbose("Library instances of module [%s] [%s]:" % (str(Module
), self
.Arch
))
2351 LibraryConsumerList
= [Module
]
2353 # "CompilerStub" is a must for Edk modules
2354 if Module
.Libraries
:
2355 Module
.Libraries
.append("CompilerStub")
2357 while len(LibraryConsumerList
) > 0:
2358 M
= LibraryConsumerList
.pop()
2359 for LibraryName
in M
.Libraries
:
2360 Library
= self
.Platform
.LibraryClasses
[LibraryName
, ':dummy:']
2362 for Key
in self
.Platform
.LibraryClasses
.data
.keys():
2363 if LibraryName
.upper() == Key
.upper():
2364 Library
= self
.Platform
.LibraryClasses
[Key
, ':dummy:']
2367 EdkLogger
.warn("build", "Library [%s] is not found" % LibraryName
, File
=str(M
),
2368 ExtraData
="\t%s [%s]" % (str(Module
), self
.Arch
))
2371 if Library
not in LibraryList
:
2372 LibraryList
.append(Library
)
2373 LibraryConsumerList
.append(Library
)
2374 EdkLogger
.verbose("\t" + LibraryName
+ " : " + str(Library
) + ' ' + str(type(Library
)))
2377 ## Calculate the priority value of the build option
2379 # @param Key Build option definition contain: TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
2381 # @retval Value Priority value based on the priority list.
2383 def CalculatePriorityValue(self
, Key
):
2384 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
.split('_')
2385 PriorityValue
= 0x11111
2387 PriorityValue
&= 0x01111
2388 if ToolChain
== "*":
2389 PriorityValue
&= 0x10111
2391 PriorityValue
&= 0x11011
2392 if CommandType
== "*":
2393 PriorityValue
&= 0x11101
2395 PriorityValue
&= 0x11110
2397 return self
.PrioList
["0x%0.5x" % PriorityValue
]
2400 ## Expand * in build option key
2402 # @param Options Options to be expanded
2404 # @retval options Options expanded
2406 def _ExpandBuildOption(self
, Options
, ModuleStyle
=None):
2413 # Construct a list contain the build options which need override.
2417 # Key[0] -- tool family
2418 # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
2420 if (Key
[0] == self
.BuildRuleFamily
and
2421 (ModuleStyle
== None or len(Key
) < 3 or (len(Key
) > 2 and Key
[2] == ModuleStyle
))):
2422 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
[1].split('_')
2423 if Target
== self
.BuildTarget
or Target
== "*":
2424 if ToolChain
== self
.ToolChain
or ToolChain
== "*":
2425 if Arch
== self
.Arch
or Arch
== "*":
2426 if Options
[Key
].startswith("="):
2427 if OverrideList
.get(Key
[1]) != None:
2428 OverrideList
.pop(Key
[1])
2429 OverrideList
[Key
[1]] = Options
[Key
]
2432 # Use the highest priority value.
2434 if (len(OverrideList
) >= 2):
2435 KeyList
= OverrideList
.keys()
2436 for Index
in range(len(KeyList
)):
2437 NowKey
= KeyList
[Index
]
2438 Target1
, ToolChain1
, Arch1
, CommandType1
, Attr1
= NowKey
.split("_")
2439 for Index1
in range(len(KeyList
) - Index
- 1):
2440 NextKey
= KeyList
[Index1
+ Index
+ 1]
2442 # Compare two Key, if one is included by another, choose the higher priority one
2444 Target2
, ToolChain2
, Arch2
, CommandType2
, Attr2
= NextKey
.split("_")
2445 if Target1
== Target2
or Target1
== "*" or Target2
== "*":
2446 if ToolChain1
== ToolChain2
or ToolChain1
== "*" or ToolChain2
== "*":
2447 if Arch1
== Arch2
or Arch1
== "*" or Arch2
== "*":
2448 if CommandType1
== CommandType2
or CommandType1
== "*" or CommandType2
== "*":
2449 if Attr1
== Attr2
or Attr1
== "*" or Attr2
== "*":
2450 if self
.CalculatePriorityValue(NowKey
) > self
.CalculatePriorityValue(NextKey
):
2451 if Options
.get((self
.BuildRuleFamily
, NextKey
)) != None:
2452 Options
.pop((self
.BuildRuleFamily
, NextKey
))
2454 if Options
.get((self
.BuildRuleFamily
, NowKey
)) != None:
2455 Options
.pop((self
.BuildRuleFamily
, NowKey
))
2458 if ModuleStyle
!= None and len (Key
) > 2:
2459 # Check Module style is EDK or EDKII.
2460 # Only append build option for the matched style module.
2461 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
2463 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
2466 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
2467 # if tool chain family doesn't match, skip it
2468 if Tool
in self
.ToolDefinition
and Family
!= "":
2469 FamilyIsNull
= False
2470 if self
.ToolDefinition
[Tool
].get(TAB_TOD_DEFINES_BUILDRULEFAMILY
, "") != "":
2471 if Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_BUILDRULEFAMILY
]:
2473 elif Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
2476 # expand any wildcard
2477 if Target
== "*" or Target
== self
.BuildTarget
:
2478 if Tag
== "*" or Tag
== self
.ToolChain
:
2479 if Arch
== "*" or Arch
== self
.Arch
:
2480 if Tool
not in BuildOptions
:
2481 BuildOptions
[Tool
] = {}
2482 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
] or Options
[Key
].startswith('='):
2483 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2485 # append options for the same tool except PATH
2487 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
2489 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2490 # Build Option Family has been checked, which need't to be checked again for family.
2491 if FamilyMatch
or FamilyIsNull
:
2495 if ModuleStyle
!= None and len (Key
) > 2:
2496 # Check Module style is EDK or EDKII.
2497 # Only append build option for the matched style module.
2498 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
2500 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
2503 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
2504 # if tool chain family doesn't match, skip it
2505 if Tool
not in self
.ToolDefinition
or Family
== "":
2507 # option has been added before
2508 if Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
2511 # expand any wildcard
2512 if Target
== "*" or Target
== self
.BuildTarget
:
2513 if Tag
== "*" or Tag
== self
.ToolChain
:
2514 if Arch
== "*" or Arch
== self
.Arch
:
2515 if Tool
not in BuildOptions
:
2516 BuildOptions
[Tool
] = {}
2517 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
] or Options
[Key
].startswith('='):
2518 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2520 # append options for the same tool except PATH
2522 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
2524 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2527 ## Append build options in platform to a module
2529 # @param Module The module to which the build options will be appened
2531 # @retval options The options appended with build options in platform
2533 def ApplyBuildOption(self
, Module
):
2534 # Get the different options for the different style module
2535 if Module
.AutoGenVersion
< 0x00010005:
2536 PlatformOptions
= self
.EdkBuildOption
2537 ModuleTypeOptions
= self
.Platform
.GetBuildOptionsByModuleType(EDK_NAME
, Module
.ModuleType
)
2539 PlatformOptions
= self
.EdkIIBuildOption
2540 ModuleTypeOptions
= self
.Platform
.GetBuildOptionsByModuleType(EDKII_NAME
, Module
.ModuleType
)
2541 ModuleTypeOptions
= self
._ExpandBuildOption
(ModuleTypeOptions
)
2542 ModuleOptions
= self
._ExpandBuildOption
(Module
.BuildOptions
)
2543 if Module
in self
.Platform
.Modules
:
2544 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
2545 PlatformModuleOptions
= self
._ExpandBuildOption
(PlatformModule
.BuildOptions
)
2547 PlatformModuleOptions
= {}
2549 BuildRuleOrder
= None
2550 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, ModuleTypeOptions
, PlatformModuleOptions
]:
2551 for Tool
in Options
:
2552 for Attr
in Options
[Tool
]:
2553 if Attr
== TAB_TOD_DEFINES_BUILDRULEORDER
:
2554 BuildRuleOrder
= Options
[Tool
][Attr
]
2556 AllTools
= set(ModuleOptions
.keys() + PlatformOptions
.keys() +
2557 PlatformModuleOptions
.keys() + ModuleTypeOptions
.keys() +
2558 self
.ToolDefinition
.keys())
2560 for Tool
in AllTools
:
2561 if Tool
not in BuildOptions
:
2562 BuildOptions
[Tool
] = {}
2564 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, ModuleTypeOptions
, PlatformModuleOptions
]:
2565 if Tool
not in Options
:
2567 for Attr
in Options
[Tool
]:
2568 Value
= Options
[Tool
][Attr
]
2570 # Do not generate it in Makefile
2572 if Attr
== TAB_TOD_DEFINES_BUILDRULEORDER
:
2574 if Attr
not in BuildOptions
[Tool
]:
2575 BuildOptions
[Tool
][Attr
] = ""
2576 # check if override is indicated
2577 if Value
.startswith('='):
2578 ToolPath
= Value
[1:]
2579 ToolPath
= mws
.handleWsMacro(ToolPath
)
2580 BuildOptions
[Tool
][Attr
] = ToolPath
2582 Value
= mws
.handleWsMacro(Value
)
2584 BuildOptions
[Tool
][Attr
] += " " + Value
2586 BuildOptions
[Tool
][Attr
] = Value
2587 if Module
.AutoGenVersion
< 0x00010005 and self
.Workspace
.UniFlag
!= None:
2589 # Override UNI flag only for EDK module.
2591 if 'BUILD' not in BuildOptions
:
2592 BuildOptions
['BUILD'] = {}
2593 BuildOptions
['BUILD']['FLAGS'] = self
.Workspace
.UniFlag
2594 return BuildOptions
, BuildRuleOrder
2596 Platform
= property(_GetPlatform
)
2597 Name
= property(_GetName
)
2598 Guid
= property(_GetGuid
)
2599 Version
= property(_GetVersion
)
2601 OutputDir
= property(_GetOutputDir
)
2602 BuildDir
= property(_GetBuildDir
)
2603 MakeFileDir
= property(_GetMakeFileDir
)
2604 FdfFile
= property(_GetFdfFile
)
2606 PcdTokenNumber
= property(_GetPcdTokenNumbers
) # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
2607 DynamicPcdList
= property(_GetDynamicPcdList
) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
2608 NonDynamicPcdList
= property(_GetNonDynamicPcdList
) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
2609 NonDynamicPcdDict
= property(_GetNonDynamicPcdDict
)
2610 PackageList
= property(_GetPackageList
)
2612 ToolDefinition
= property(_GetToolDefinition
) # toolcode : tool path
2613 ToolDefinitionFile
= property(_GetToolDefFile
) # toolcode : lib path
2614 ToolChainFamily
= property(_GetToolChainFamily
)
2615 BuildRuleFamily
= property(_GetBuildRuleFamily
)
2616 BuildOption
= property(_GetBuildOptions
) # toolcode : option
2617 EdkBuildOption
= property(_GetEdkBuildOptions
) # edktoolcode : option
2618 EdkIIBuildOption
= property(_GetEdkIIBuildOptions
) # edkiitoolcode : option
2620 BuildCommand
= property(_GetBuildCommand
)
2621 BuildRule
= property(_GetBuildRule
)
2622 ModuleAutoGenList
= property(_GetModuleAutoGenList
)
2623 LibraryAutoGenList
= property(_GetLibraryAutoGenList
)
2624 GenFdsCommand
= property(_GenFdsCommand
)
2626 ## ModuleAutoGen class
2628 # This class encapsules the AutoGen behaviors for the build tools. In addition to
2629 # the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according
2630 # to the [depex] section in module's inf file.
2632 class ModuleAutoGen(AutoGen
):
2633 ## Cache the timestamps of metafiles of every module in a class variable
2637 ## The real constructor of ModuleAutoGen
2639 # This method is not supposed to be called by users of ModuleAutoGen. It's
2640 # only used by factory method __new__() to do real initialization work for an
2641 # object of ModuleAutoGen
2643 # @param Workspace EdkIIWorkspaceBuild object
2644 # @param ModuleFile The path of module file
2645 # @param Target Build target (DEBUG, RELEASE)
2646 # @param Toolchain Name of tool chain
2647 # @param Arch The arch the module supports
2648 # @param PlatformFile Platform meta-file
2650 def _Init(self
, Workspace
, ModuleFile
, Target
, Toolchain
, Arch
, PlatformFile
):
2651 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen module [%s] [%s]" % (ModuleFile
, Arch
))
2652 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (ModuleFile
, Arch
, Toolchain
, Target
)
2654 self
.Workspace
= Workspace
2655 self
.WorkspaceDir
= Workspace
.WorkspaceDir
2657 self
.MetaFile
= ModuleFile
2658 self
.PlatformInfo
= PlatformAutoGen(Workspace
, PlatformFile
, Target
, Toolchain
, Arch
)
2659 # check if this module is employed by active platform
2660 if not self
.PlatformInfo
.ValidModule(self
.MetaFile
):
2661 EdkLogger
.verbose("Module [%s] for [%s] is not employed by active platform\n" \
2662 % (self
.MetaFile
, Arch
))
2665 self
.SourceDir
= self
.MetaFile
.SubDir
2666 self
.SourceDir
= mws
.relpath(self
.SourceDir
, self
.WorkspaceDir
)
2668 self
.SourceOverrideDir
= None
2669 # use overrided path defined in DSC file
2670 if self
.MetaFile
.Key
in GlobalData
.gOverrideDir
:
2671 self
.SourceOverrideDir
= GlobalData
.gOverrideDir
[self
.MetaFile
.Key
]
2673 self
.ToolChain
= Toolchain
2674 self
.BuildTarget
= Target
2676 self
.ToolChainFamily
= self
.PlatformInfo
.ToolChainFamily
2677 self
.BuildRuleFamily
= self
.PlatformInfo
.BuildRuleFamily
2679 self
.IsMakeFileCreated
= False
2680 self
.IsCodeFileCreated
= False
2681 self
.IsAsBuiltInfCreated
= False
2682 self
.DepexGenerated
= False
2684 self
.BuildDatabase
= self
.Workspace
.BuildDatabase
2685 self
.BuildRuleOrder
= None
2690 self
._Version
= None
2691 self
._ModuleType
= None
2692 self
._ComponentType
= None
2693 self
._PcdIsDriver
= None
2694 self
._AutoGenVersion
= None
2695 self
._LibraryFlag
= None
2696 self
._CustomMakefile
= None
2699 self
._BuildDir
= None
2700 self
._OutputDir
= None
2701 self
._DebugDir
= None
2702 self
._MakeFileDir
= None
2704 self
._IncludePathList
= None
2705 self
._IncludePathLength
= 0
2706 self
._AutoGenFileList
= None
2707 self
._UnicodeFileList
= None
2708 self
._VfrFileList
= None
2709 self
._IdfFileList
= None
2710 self
._SourceFileList
= None
2711 self
._ObjectFileList
= None
2712 self
._BinaryFileList
= None
2714 self
._DependentPackageList
= None
2715 self
._DependentLibraryList
= None
2716 self
._LibraryAutoGenList
= None
2717 self
._DerivedPackageList
= None
2718 self
._ModulePcdList
= None
2719 self
._LibraryPcdList
= None
2720 self
._PcdComments
= sdict()
2721 self
._GuidList
= None
2722 self
._GuidsUsedByPcd
= None
2723 self
._GuidComments
= sdict()
2724 self
._ProtocolList
= None
2725 self
._ProtocolComments
= sdict()
2726 self
._PpiList
= None
2727 self
._PpiComments
= sdict()
2728 self
._DepexList
= None
2729 self
._DepexExpressionList
= None
2730 self
._BuildOption
= None
2731 self
._BuildOptionIncPathList
= None
2732 self
._BuildTargets
= None
2733 self
._IntroBuildTargetList
= None
2734 self
._FinalBuildTargetList
= None
2735 self
._FileTypes
= None
2736 self
._BuildRules
= None
2738 self
._TimeStampPath
= None
2740 self
.AutoGenDepSet
= set()
2743 ## The Modules referenced to this Library
2744 # Only Library has this attribute
2745 self
._ReferenceModules
= []
2747 ## Store the FixedAtBuild Pcds
2749 self
._FixedAtBuildPcds
= []
2754 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
2756 # Get FixedAtBuild Pcds of this Module
2757 def _GetFixedAtBuildPcds(self
):
2758 if self
._FixedAtBuildPcds
:
2759 return self
._FixedAtBuildPcds
2760 for Pcd
in self
.ModulePcdList
:
2761 if Pcd
.Type
!= "FixedAtBuild":
2763 if Pcd
not in self
._FixedAtBuildPcds
:
2764 self
._FixedAtBuildPcds
.append(Pcd
)
2766 return self
._FixedAtBuildPcds
2768 def _GetUniqueBaseName(self
):
2769 BaseName
= self
.Name
2770 for Module
in self
.PlatformInfo
.ModuleAutoGenList
:
2771 if Module
.MetaFile
== self
.MetaFile
:
2773 if Module
.Name
== self
.Name
:
2774 if uuid
.UUID(Module
.Guid
) == uuid
.UUID(self
.Guid
):
2775 EdkLogger
.error("build", FILE_DUPLICATED
, 'Modules have same BaseName and FILE_GUID:\n'
2776 ' %s\n %s' % (Module
.MetaFile
, self
.MetaFile
))
2777 BaseName
= '%s_%s' % (self
.Name
, self
.Guid
)
2780 # Macros could be used in build_rule.txt (also Makefile)
2781 def _GetMacros(self
):
2782 if self
._Macro
== None:
2783 self
._Macro
= sdict()
2784 self
._Macro
["WORKSPACE" ] = self
.WorkspaceDir
2785 self
._Macro
["MODULE_NAME" ] = self
.Name
2786 self
._Macro
["MODULE_NAME_GUID" ] = self
._GetUniqueBaseName
()
2787 self
._Macro
["MODULE_GUID" ] = self
.Guid
2788 self
._Macro
["MODULE_VERSION" ] = self
.Version
2789 self
._Macro
["MODULE_TYPE" ] = self
.ModuleType
2790 self
._Macro
["MODULE_FILE" ] = str(self
.MetaFile
)
2791 self
._Macro
["MODULE_FILE_BASE_NAME" ] = self
.MetaFile
.BaseName
2792 self
._Macro
["MODULE_RELATIVE_DIR" ] = self
.SourceDir
2793 self
._Macro
["MODULE_DIR" ] = self
.SourceDir
2795 self
._Macro
["BASE_NAME" ] = self
.Name
2797 self
._Macro
["ARCH" ] = self
.Arch
2798 self
._Macro
["TOOLCHAIN" ] = self
.ToolChain
2799 self
._Macro
["TOOLCHAIN_TAG" ] = self
.ToolChain
2800 self
._Macro
["TOOL_CHAIN_TAG" ] = self
.ToolChain
2801 self
._Macro
["TARGET" ] = self
.BuildTarget
2803 self
._Macro
["BUILD_DIR" ] = self
.PlatformInfo
.BuildDir
2804 self
._Macro
["BIN_DIR" ] = os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)
2805 self
._Macro
["LIB_DIR" ] = os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)
2806 self
._Macro
["MODULE_BUILD_DIR" ] = self
.BuildDir
2807 self
._Macro
["OUTPUT_DIR" ] = self
.OutputDir
2808 self
._Macro
["DEBUG_DIR" ] = self
.DebugDir
2809 self
._Macro
["DEST_DIR_OUTPUT" ] = self
.OutputDir
2810 self
._Macro
["DEST_DIR_DEBUG" ] = self
.DebugDir
2811 self
._Macro
["PLATFORM_NAME" ] = self
.PlatformInfo
.Name
2812 self
._Macro
["PLATFORM_GUID" ] = self
.PlatformInfo
.Guid
2813 self
._Macro
["PLATFORM_VERSION" ] = self
.PlatformInfo
.Version
2814 self
._Macro
["PLATFORM_RELATIVE_DIR" ] = self
.PlatformInfo
.SourceDir
2815 self
._Macro
["PLATFORM_DIR" ] = mws
.join(self
.WorkspaceDir
, self
.PlatformInfo
.SourceDir
)
2816 self
._Macro
["PLATFORM_OUTPUT_DIR" ] = self
.PlatformInfo
.OutputDir
2819 ## Return the module build data object
2820 def _GetModule(self
):
2821 if self
._Module
== None:
2822 self
._Module
= self
.Workspace
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
2825 ## Return the module name
2826 def _GetBaseName(self
):
2827 return self
.Module
.BaseName
2829 ## Return the module DxsFile if exist
2830 def _GetDxsFile(self
):
2831 return self
.Module
.DxsFile
2833 ## Return the module SourceOverridePath
2834 def _GetSourceOverridePath(self
):
2835 return self
.Module
.SourceOverridePath
2837 ## Return the module meta-file GUID
2840 # To build same module more than once, the module path with FILE_GUID overridden has
2841 # the file name FILE_GUIDmodule.inf, but the relative path (self.MetaFile.File) is the realy path
2842 # in DSC. The overridden GUID can be retrieved from file name
2844 if os
.path
.basename(self
.MetaFile
.File
) != os
.path
.basename(self
.MetaFile
.Path
):
2846 # Length of GUID is 36
2848 return os
.path
.basename(self
.MetaFile
.Path
)[:36]
2849 return self
.Module
.Guid
2851 ## Return the module version
2852 def _GetVersion(self
):
2853 return self
.Module
.Version
2855 ## Return the module type
2856 def _GetModuleType(self
):
2857 return self
.Module
.ModuleType
2859 ## Return the component type (for Edk.x style of module)
2860 def _GetComponentType(self
):
2861 return self
.Module
.ComponentType
2863 ## Return the build type
2864 def _GetBuildType(self
):
2865 return self
.Module
.BuildType
2867 ## Return the PCD_IS_DRIVER setting
2868 def _GetPcdIsDriver(self
):
2869 return self
.Module
.PcdIsDriver
2871 ## Return the autogen version, i.e. module meta-file version
2872 def _GetAutoGenVersion(self
):
2873 return self
.Module
.AutoGenVersion
2875 ## Check if the module is library or not
2876 def _IsLibrary(self
):
2877 if self
._LibraryFlag
== None:
2878 if self
.Module
.LibraryClass
!= None and self
.Module
.LibraryClass
!= []:
2879 self
._LibraryFlag
= True
2881 self
._LibraryFlag
= False
2882 return self
._LibraryFlag
2884 ## Check if the module is binary module or not
2885 def _IsBinaryModule(self
):
2886 return self
.Module
.IsBinaryModule
2888 ## Return the directory to store intermediate files of the module
2889 def _GetBuildDir(self
):
2890 if self
._BuildDir
== None:
2891 self
._BuildDir
= path
.join(
2892 self
.PlatformInfo
.BuildDir
,
2895 self
.MetaFile
.BaseName
2897 CreateDirectory(self
._BuildDir
)
2898 return self
._BuildDir
2900 ## Return the directory to store the intermediate object files of the mdoule
2901 def _GetOutputDir(self
):
2902 if self
._OutputDir
== None:
2903 self
._OutputDir
= path
.join(self
.BuildDir
, "OUTPUT")
2904 CreateDirectory(self
._OutputDir
)
2905 return self
._OutputDir
2907 ## Return the directory to store auto-gened source files of the mdoule
2908 def _GetDebugDir(self
):
2909 if self
._DebugDir
== None:
2910 self
._DebugDir
= path
.join(self
.BuildDir
, "DEBUG")
2911 CreateDirectory(self
._DebugDir
)
2912 return self
._DebugDir
2914 ## Return the path of custom file
2915 def _GetCustomMakefile(self
):
2916 if self
._CustomMakefile
== None:
2917 self
._CustomMakefile
= {}
2918 for Type
in self
.Module
.CustomMakefile
:
2919 if Type
in gMakeTypeMap
:
2920 MakeType
= gMakeTypeMap
[Type
]
2923 if self
.SourceOverrideDir
!= None:
2924 File
= os
.path
.join(self
.SourceOverrideDir
, self
.Module
.CustomMakefile
[Type
])
2925 if not os
.path
.exists(File
):
2926 File
= os
.path
.join(self
.SourceDir
, self
.Module
.CustomMakefile
[Type
])
2928 File
= os
.path
.join(self
.SourceDir
, self
.Module
.CustomMakefile
[Type
])
2929 self
._CustomMakefile
[MakeType
] = File
2930 return self
._CustomMakefile
2932 ## Return the directory of the makefile
2934 # @retval string The directory string of module's makefile
2936 def _GetMakeFileDir(self
):
2937 return self
.BuildDir
2939 ## Return build command string
2941 # @retval string Build command string
2943 def _GetBuildCommand(self
):
2944 return self
.PlatformInfo
.BuildCommand
2946 ## Get object list of all packages the module and its dependent libraries belong to
2948 # @retval list The list of package object
2950 def _GetDerivedPackageList(self
):
2952 for M
in [self
.Module
] + self
.DependentLibraryList
:
2953 for Package
in M
.Packages
:
2954 if Package
in PackageList
:
2956 PackageList
.append(Package
)
2959 ## Get the depex string
2961 # @return : a string contain all depex expresion.
2962 def _GetDepexExpresionString(self
):
2965 ## DPX_SOURCE IN Define section.
2966 if self
.Module
.DxsFile
:
2968 for M
in [self
.Module
] + self
.DependentLibraryList
:
2969 Filename
= M
.MetaFile
.Path
2970 InfObj
= InfSectionParser
.InfSectionParser(Filename
)
2971 DepexExpresionList
= InfObj
.GetDepexExpresionList()
2972 for DepexExpresion
in DepexExpresionList
:
2973 for key
in DepexExpresion
.keys():
2974 Arch
, ModuleType
= key
2975 DepexExpr
= [x
for x
in DepexExpresion
[key
] if not str(x
).startswith('#')]
2976 # the type of build module is USER_DEFINED.
2977 # All different DEPEX section tags would be copied into the As Built INF file
2978 # and there would be separate DEPEX section tags
2979 if self
.ModuleType
.upper() == SUP_MODULE_USER_DEFINED
:
2980 if (Arch
.upper() == self
.Arch
.upper()) and (ModuleType
.upper() != TAB_ARCH_COMMON
):
2981 DepexList
.append({(Arch
, ModuleType
): DepexExpr
})
2983 if Arch
.upper() == TAB_ARCH_COMMON
or \
2984 (Arch
.upper() == self
.Arch
.upper() and \
2985 ModuleType
.upper() in [TAB_ARCH_COMMON
, self
.ModuleType
.upper()]):
2986 DepexList
.append({(Arch
, ModuleType
): DepexExpr
})
2988 #the type of build module is USER_DEFINED.
2989 if self
.ModuleType
.upper() == SUP_MODULE_USER_DEFINED
:
2990 for Depex
in DepexList
:
2991 for key
in Depex
.keys():
2992 DepexStr
+= '[Depex.%s.%s]\n' % key
2993 DepexStr
+= '\n'.join(['# '+ val
for val
in Depex
[key
]])
2996 return '[Depex.%s]\n' % self
.Arch
2999 #the type of build module not is USER_DEFINED.
3001 for Depex
in DepexList
:
3006 for D
in Depex
.values():
3007 DepexStr
+= ' '.join([val
for val
in D
])
3008 Index
= DepexStr
.find('END')
3009 if Index
> -1 and Index
== len(DepexStr
) - 3:
3010 DepexStr
= DepexStr
[:-3]
3011 DepexStr
= DepexStr
.strip()
3014 DepexStr
= DepexStr
.lstrip('(').rstrip(')').strip()
3016 return '[Depex.%s]\n' % self
.Arch
3017 return '[Depex.%s]\n# ' % self
.Arch
+ DepexStr
3019 ## Merge dependency expression
3021 # @retval list The token list of the dependency expression after parsed
3023 def _GetDepexTokenList(self
):
3024 if self
._DepexList
== None:
3025 self
._DepexList
= {}
3026 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
3027 return self
._DepexList
3029 self
._DepexList
[self
.ModuleType
] = []
3031 for ModuleType
in self
._DepexList
:
3032 DepexList
= self
._DepexList
[ModuleType
]
3034 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
3036 for M
in [self
.Module
] + self
.DependentLibraryList
:
3038 for D
in M
.Depex
[self
.Arch
, ModuleType
]:
3040 DepexList
.append('AND')
3041 DepexList
.append('(')
3043 if DepexList
[-1] == 'END': # no need of a END at this time
3045 DepexList
.append(')')
3048 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexList
))
3049 if 'BEFORE' in DepexList
or 'AFTER' in DepexList
:
3051 if len(DepexList
) > 0:
3052 EdkLogger
.verbose('')
3053 return self
._DepexList
3055 ## Merge dependency expression
3057 # @retval list The token list of the dependency expression after parsed
3059 def _GetDepexExpressionTokenList(self
):
3060 if self
._DepexExpressionList
== None:
3061 self
._DepexExpressionList
= {}
3062 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
3063 return self
._DepexExpressionList
3065 self
._DepexExpressionList
[self
.ModuleType
] = ''
3067 for ModuleType
in self
._DepexExpressionList
:
3068 DepexExpressionList
= self
._DepexExpressionList
[ModuleType
]
3070 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
3072 for M
in [self
.Module
] + self
.DependentLibraryList
:
3074 for D
in M
.DepexExpression
[self
.Arch
, ModuleType
]:
3075 if DepexExpressionList
!= '':
3076 DepexExpressionList
+= ' AND '
3077 DepexExpressionList
+= '('
3078 DepexExpressionList
+= D
3079 DepexExpressionList
= DepexExpressionList
.rstrip('END').strip()
3080 DepexExpressionList
+= ')'
3083 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexExpressionList
))
3084 if 'BEFORE' in DepexExpressionList
or 'AFTER' in DepexExpressionList
:
3086 if len(DepexExpressionList
) > 0:
3087 EdkLogger
.verbose('')
3088 self
._DepexExpressionList
[ModuleType
] = DepexExpressionList
3089 return self
._DepexExpressionList
3091 ## Return the list of specification version required for the module
3093 # @retval list The list of specification defined in module file
3095 def _GetSpecification(self
):
3096 return self
.Module
.Specification
3098 ## Tool option for the module build
3100 # @param PlatformInfo The object of PlatformBuildInfo
3101 # @retval dict The dict containing valid options
3103 def _GetModuleBuildOption(self
):
3104 if self
._BuildOption
== None:
3105 self
._BuildOption
, self
.BuildRuleOrder
= self
.PlatformInfo
.ApplyBuildOption(self
.Module
)
3106 if self
.BuildRuleOrder
:
3107 self
.BuildRuleOrder
= ['.%s' % Ext
for Ext
in self
.BuildRuleOrder
.split()]
3108 return self
._BuildOption
3110 ## Get include path list from tool option for the module build
3112 # @retval list The include path list
3114 def _GetBuildOptionIncPathList(self
):
3115 if self
._BuildOptionIncPathList
== None:
3117 # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
3118 # is the former use /I , the Latter used -I to specify include directories
3120 if self
.PlatformInfo
.ToolChainFamily
in ('MSFT'):
3121 gBuildOptIncludePattern
= re
.compile(r
"(?:.*?)/I[ \t]*([^ ]*)", re
.MULTILINE | re
.DOTALL
)
3122 elif self
.PlatformInfo
.ToolChainFamily
in ('INTEL', 'GCC', 'RVCT'):
3123 gBuildOptIncludePattern
= re
.compile(r
"(?:.*?)-I[ \t]*([^ ]*)", re
.MULTILINE | re
.DOTALL
)
3126 # New ToolChainFamily, don't known whether there is option to specify include directories
3128 self
._BuildOptionIncPathList
= []
3129 return self
._BuildOptionIncPathList
3131 BuildOptionIncPathList
= []
3132 for Tool
in ('CC', 'PP', 'VFRPP', 'ASLPP', 'ASLCC', 'APP', 'ASM'):
3135 FlagOption
= self
.BuildOption
[Tool
][Attr
]
3139 if self
.PlatformInfo
.ToolChainFamily
!= 'RVCT':
3140 IncPathList
= [NormPath(Path
, self
.Macros
) for Path
in gBuildOptIncludePattern
.findall(FlagOption
)]
3143 # RVCT may specify a list of directory seperated by commas
3146 for Path
in gBuildOptIncludePattern
.findall(FlagOption
):
3147 PathList
= GetSplitList(Path
, TAB_COMMA_SPLIT
)
3148 IncPathList
+= [NormPath(PathEntry
, self
.Macros
) for PathEntry
in PathList
]
3151 # EDK II modules must not reference header files outside of the packages they depend on or
3152 # within the module's directory tree. Report error if violation.
3154 if self
.AutoGenVersion
>= 0x00010005 and len(IncPathList
) > 0:
3155 for Path
in IncPathList
:
3156 if (Path
not in self
.IncludePathList
) and (CommonPath([Path
, self
.MetaFile
.Dir
]) != self
.MetaFile
.Dir
):
3157 ErrMsg
= "The include directory for the EDK II module in this line is invalid %s specified in %s FLAGS '%s'" % (Path
, Tool
, FlagOption
)
3158 EdkLogger
.error("build",
3161 File
=str(self
.MetaFile
))
3164 BuildOptionIncPathList
+= IncPathList
3166 self
._BuildOptionIncPathList
= BuildOptionIncPathList
3168 return self
._BuildOptionIncPathList
3170 ## Return a list of files which can be built from source
3172 # What kind of files can be built is determined by build rules in
3173 # $(CONF_DIRECTORY)/build_rule.txt and toolchain family.
3175 def _GetSourceFileList(self
):
3176 if self
._SourceFileList
== None:
3177 self
._SourceFileList
= []
3178 for F
in self
.Module
.Sources
:
3180 if F
.TagName
not in ("", "*", self
.ToolChain
):
3181 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "The toolchain [%s] for processing file [%s] is found, "
3182 "but [%s] is needed" % (F
.TagName
, str(F
), self
.ToolChain
))
3184 # match tool chain family
3185 if F
.ToolChainFamily
not in ("", "*", self
.ToolChainFamily
):
3188 "The file [%s] must be built by tools of [%s], " \
3189 "but current toolchain family is [%s]" \
3190 % (str(F
), F
.ToolChainFamily
, self
.ToolChainFamily
))
3193 # add the file path into search path list for file including
3194 if F
.Dir
not in self
.IncludePathList
and self
.AutoGenVersion
>= 0x00010005:
3195 self
.IncludePathList
.insert(0, F
.Dir
)
3196 self
._SourceFileList
.append(F
)
3198 self
._MatchBuildRuleOrder
(self
._SourceFileList
)
3200 for F
in self
._SourceFileList
:
3201 self
._ApplyBuildRule
(F
, TAB_UNKNOWN_FILE
)
3202 return self
._SourceFileList
3204 def _MatchBuildRuleOrder(self
, FileList
):
3206 self
._GetModuleBuildOption
()
3207 for SingleFile
in FileList
:
3208 if self
.BuildRuleOrder
and SingleFile
.Ext
in self
.BuildRuleOrder
and SingleFile
.Ext
in self
.BuildRules
:
3209 key
= SingleFile
.Path
.split(SingleFile
.Ext
)[0]
3210 if key
in Order_Dict
:
3211 Order_Dict
[key
].append(SingleFile
.Ext
)
3213 Order_Dict
[key
] = [SingleFile
.Ext
]
3216 for F
in Order_Dict
:
3217 if len(Order_Dict
[F
]) > 1:
3218 Order_Dict
[F
].sort(key
=lambda i
: self
.BuildRuleOrder
.index(i
))
3219 for Ext
in Order_Dict
[F
][1:]:
3220 RemoveList
.append(F
+ Ext
)
3222 for item
in RemoveList
:
3223 FileList
.remove(item
)
3227 ## Return the list of unicode files
3228 def _GetUnicodeFileList(self
):
3229 if self
._UnicodeFileList
== None:
3230 if TAB_UNICODE_FILE
in self
.FileTypes
:
3231 self
._UnicodeFileList
= self
.FileTypes
[TAB_UNICODE_FILE
]
3233 self
._UnicodeFileList
= []
3234 return self
._UnicodeFileList
3236 ## Return the list of vfr files
3237 def _GetVfrFileList(self
):
3238 if self
._VfrFileList
== None:
3239 if TAB_VFR_FILE
in self
.FileTypes
:
3240 self
._VfrFileList
= self
.FileTypes
[TAB_VFR_FILE
]
3242 self
._VfrFileList
= []
3243 return self
._VfrFileList
3245 ## Return the list of Image Definition files
3246 def _GetIdfFileList(self
):
3247 if self
._IdfFileList
== None:
3248 if TAB_IMAGE_FILE
in self
.FileTypes
:
3249 self
._IdfFileList
= self
.FileTypes
[TAB_IMAGE_FILE
]
3251 self
._IdfFileList
= []
3252 return self
._IdfFileList
3254 ## Return a list of files which can be built from binary
3256 # "Build" binary files are just to copy them to build directory.
3258 # @retval list The list of files which can be built later
3260 def _GetBinaryFiles(self
):
3261 if self
._BinaryFileList
== None:
3262 self
._BinaryFileList
= []
3263 for F
in self
.Module
.Binaries
:
3264 if F
.Target
not in ['COMMON', '*'] and F
.Target
!= self
.BuildTarget
:
3266 self
._BinaryFileList
.append(F
)
3267 self
._ApplyBuildRule
(F
, F
.Type
)
3268 return self
._BinaryFileList
3270 def _GetBuildRules(self
):
3271 if self
._BuildRules
== None:
3273 BuildRuleDatabase
= self
.PlatformInfo
.BuildRule
3274 for Type
in BuildRuleDatabase
.FileTypeList
:
3275 #first try getting build rule by BuildRuleFamily
3276 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.BuildRuleFamily
]
3278 # build type is always module type, but ...
3279 if self
.ModuleType
!= self
.BuildType
:
3280 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.BuildRuleFamily
]
3281 #second try getting build rule by ToolChainFamily
3283 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.ToolChainFamily
]
3285 # build type is always module type, but ...
3286 if self
.ModuleType
!= self
.BuildType
:
3287 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.ToolChainFamily
]
3290 RuleObject
= RuleObject
.Instantiate(self
.Macros
)
3291 BuildRules
[Type
] = RuleObject
3292 for Ext
in RuleObject
.SourceFileExtList
:
3293 BuildRules
[Ext
] = RuleObject
3294 self
._BuildRules
= BuildRules
3295 return self
._BuildRules
3297 def _ApplyBuildRule(self
, File
, FileType
):
3298 if self
._BuildTargets
== None:
3299 self
._IntroBuildTargetList
= set()
3300 self
._FinalBuildTargetList
= set()
3301 self
._BuildTargets
= {}
3302 self
._FileTypes
= {}
3304 SubDirectory
= os
.path
.join(self
.OutputDir
, File
.SubDir
)
3305 if not os
.path
.exists(SubDirectory
):
3306 CreateDirectory(SubDirectory
)
3312 # Make sure to get build rule order value
3314 self
._GetModuleBuildOption
()
3316 while Index
< len(SourceList
):
3317 Source
= SourceList
[Index
]
3321 CreateDirectory(Source
.Dir
)
3323 if File
.IsBinary
and File
== Source
and self
._BinaryFileList
!= None and File
in self
._BinaryFileList
:
3324 # Skip all files that are not binary libraries
3325 if not self
.IsLibrary
:
3327 RuleObject
= self
.BuildRules
[TAB_DEFAULT_BINARY_FILE
]
3328 elif FileType
in self
.BuildRules
:
3329 RuleObject
= self
.BuildRules
[FileType
]
3330 elif Source
.Ext
in self
.BuildRules
:
3331 RuleObject
= self
.BuildRules
[Source
.Ext
]
3333 # stop at no more rules
3335 self
._FinalBuildTargetList
.add(LastTarget
)
3338 FileType
= RuleObject
.SourceFileType
3339 if FileType
not in self
._FileTypes
:
3340 self
._FileTypes
[FileType
] = set()
3341 self
._FileTypes
[FileType
].add(Source
)
3343 # stop at STATIC_LIBRARY for library
3344 if self
.IsLibrary
and FileType
== TAB_STATIC_LIBRARY
:
3346 self
._FinalBuildTargetList
.add(LastTarget
)
3349 Target
= RuleObject
.Apply(Source
, self
.BuildRuleOrder
)
3352 self
._FinalBuildTargetList
.add(LastTarget
)
3354 elif not Target
.Outputs
:
3355 # Only do build for target with outputs
3356 self
._FinalBuildTargetList
.add(Target
)
3358 if FileType
not in self
._BuildTargets
:
3359 self
._BuildTargets
[FileType
] = set()
3360 self
._BuildTargets
[FileType
].add(Target
)
3362 if not Source
.IsBinary
and Source
== File
:
3363 self
._IntroBuildTargetList
.add(Target
)
3365 # to avoid cyclic rule
3366 if FileType
in RuleChain
:
3369 RuleChain
.append(FileType
)
3370 SourceList
.extend(Target
.Outputs
)
3372 FileType
= TAB_UNKNOWN_FILE
3374 def _GetTargets(self
):
3375 if self
._BuildTargets
== None:
3376 self
._IntroBuildTargetList
= set()
3377 self
._FinalBuildTargetList
= set()
3378 self
._BuildTargets
= {}
3379 self
._FileTypes
= {}
3381 #TRICK: call _GetSourceFileList to apply build rule for source files
3382 if self
.SourceFileList
:
3385 #TRICK: call _GetBinaryFileList to apply build rule for binary files
3386 if self
.BinaryFileList
:
3389 return self
._BuildTargets
3391 def _GetIntroTargetList(self
):
3393 return self
._IntroBuildTargetList
3395 def _GetFinalTargetList(self
):
3397 return self
._FinalBuildTargetList
3399 def _GetFileTypes(self
):
3401 return self
._FileTypes
3403 ## Get the list of package object the module depends on
3405 # @retval list The package object list
3407 def _GetDependentPackageList(self
):
3408 return self
.Module
.Packages
3410 ## Return the list of auto-generated code file
3412 # @retval list The list of auto-generated file
3414 def _GetAutoGenFileList(self
):
3415 UniStringAutoGenC
= True
3416 IdfStringAutoGenC
= True
3417 UniStringBinBuffer
= StringIO()
3418 IdfGenBinBuffer
= StringIO()
3419 if self
.BuildType
== 'UEFI_HII':
3420 UniStringAutoGenC
= False
3421 IdfStringAutoGenC
= False
3422 if self
._AutoGenFileList
== None:
3423 self
._AutoGenFileList
= {}
3424 AutoGenC
= TemplateString()
3425 AutoGenH
= TemplateString()
3426 StringH
= TemplateString()
3427 StringIdf
= TemplateString()
3428 GenC
.CreateCode(self
, AutoGenC
, AutoGenH
, StringH
, UniStringAutoGenC
, UniStringBinBuffer
, StringIdf
, IdfStringAutoGenC
, IdfGenBinBuffer
)
3430 # AutoGen.c is generated if there are library classes in inf, or there are object files
3432 if str(AutoGenC
) != "" and (len(self
.Module
.LibraryClasses
) > 0
3433 or TAB_OBJECT_FILE
in self
.FileTypes
):
3434 AutoFile
= PathClass(gAutoGenCodeFileName
, self
.DebugDir
)
3435 self
._AutoGenFileList
[AutoFile
] = str(AutoGenC
)
3436 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3437 if str(AutoGenH
) != "":
3438 AutoFile
= PathClass(gAutoGenHeaderFileName
, self
.DebugDir
)
3439 self
._AutoGenFileList
[AutoFile
] = str(AutoGenH
)
3440 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3441 if str(StringH
) != "":
3442 AutoFile
= PathClass(gAutoGenStringFileName
% {"module_name":self
.Name
}, self
.DebugDir
)
3443 self
._AutoGenFileList
[AutoFile
] = str(StringH
)
3444 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3445 if UniStringBinBuffer
!= None and UniStringBinBuffer
.getvalue() != "":
3446 AutoFile
= PathClass(gAutoGenStringFormFileName
% {"module_name":self
.Name
}, self
.OutputDir
)
3447 self
._AutoGenFileList
[AutoFile
] = UniStringBinBuffer
.getvalue()
3448 AutoFile
.IsBinary
= True
3449 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3450 if UniStringBinBuffer
!= None:
3451 UniStringBinBuffer
.close()
3452 if str(StringIdf
) != "":
3453 AutoFile
= PathClass(gAutoGenImageDefFileName
% {"module_name":self
.Name
}, self
.DebugDir
)
3454 self
._AutoGenFileList
[AutoFile
] = str(StringIdf
)
3455 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3456 if IdfGenBinBuffer
!= None and IdfGenBinBuffer
.getvalue() != "":
3457 AutoFile
= PathClass(gAutoGenIdfFileName
% {"module_name":self
.Name
}, self
.OutputDir
)
3458 self
._AutoGenFileList
[AutoFile
] = IdfGenBinBuffer
.getvalue()
3459 AutoFile
.IsBinary
= True
3460 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3461 if IdfGenBinBuffer
!= None:
3462 IdfGenBinBuffer
.close()
3463 return self
._AutoGenFileList
3465 ## Return the list of library modules explicitly or implicityly used by this module
3466 def _GetLibraryList(self
):
3467 if self
._DependentLibraryList
== None:
3468 # only merge library classes and PCD for non-library module
3470 self
._DependentLibraryList
= []
3472 if self
.AutoGenVersion
< 0x00010005:
3473 self
._DependentLibraryList
= self
.PlatformInfo
.ResolveLibraryReference(self
.Module
)
3475 self
._DependentLibraryList
= self
.PlatformInfo
.ApplyLibraryInstance(self
.Module
)
3476 return self
._DependentLibraryList
3479 def UpdateComments(Recver
, Src
):
3481 if Key
not in Recver
:
3483 Recver
[Key
].extend(Src
[Key
])
3484 ## Get the list of PCDs from current module
3486 # @retval list The list of PCD
3488 def _GetModulePcdList(self
):
3489 if self
._ModulePcdList
== None:
3490 # apply PCD settings from platform
3491 self
._ModulePcdList
= self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, self
.Module
.Pcds
)
3492 self
.UpdateComments(self
._PcdComments
, self
.Module
.PcdComments
)
3493 return self
._ModulePcdList
3495 ## Get the list of PCDs from dependent libraries
3497 # @retval list The list of PCD
3499 def _GetLibraryPcdList(self
):
3500 if self
._LibraryPcdList
== None:
3502 if not self
.IsLibrary
:
3503 # get PCDs from dependent libraries
3504 for Library
in self
.DependentLibraryList
:
3505 self
.UpdateComments(self
._PcdComments
, Library
.PcdComments
)
3506 for Key
in Library
.Pcds
:
3507 # skip duplicated PCDs
3508 if Key
in self
.Module
.Pcds
or Key
in Pcds
:
3510 Pcds
[Key
] = copy
.copy(Library
.Pcds
[Key
])
3511 # apply PCD settings from platform
3512 self
._LibraryPcdList
= self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, Pcds
)
3514 self
._LibraryPcdList
= []
3515 return self
._LibraryPcdList
3517 ## Get the GUID value mapping
3519 # @retval dict The mapping between GUID cname and its value
3521 def _GetGuidList(self
):
3522 if self
._GuidList
== None:
3523 self
._GuidList
= sdict()
3524 self
._GuidList
.update(self
.Module
.Guids
)
3525 for Library
in self
.DependentLibraryList
:
3526 self
._GuidList
.update(Library
.Guids
)
3527 self
.UpdateComments(self
._GuidComments
, Library
.GuidComments
)
3528 self
.UpdateComments(self
._GuidComments
, self
.Module
.GuidComments
)
3529 return self
._GuidList
3531 def GetGuidsUsedByPcd(self
):
3532 if self
._GuidsUsedByPcd
== None:
3533 self
._GuidsUsedByPcd
= sdict()
3534 self
._GuidsUsedByPcd
.update(self
.Module
.GetGuidsUsedByPcd())
3535 for Library
in self
.DependentLibraryList
:
3536 self
._GuidsUsedByPcd
.update(Library
.GetGuidsUsedByPcd())
3537 return self
._GuidsUsedByPcd
3538 ## Get the protocol value mapping
3540 # @retval dict The mapping between protocol cname and its value
3542 def _GetProtocolList(self
):
3543 if self
._ProtocolList
== None:
3544 self
._ProtocolList
= sdict()
3545 self
._ProtocolList
.update(self
.Module
.Protocols
)
3546 for Library
in self
.DependentLibraryList
:
3547 self
._ProtocolList
.update(Library
.Protocols
)
3548 self
.UpdateComments(self
._ProtocolComments
, Library
.ProtocolComments
)
3549 self
.UpdateComments(self
._ProtocolComments
, self
.Module
.ProtocolComments
)
3550 return self
._ProtocolList
3552 ## Get the PPI value mapping
3554 # @retval dict The mapping between PPI cname and its value
3556 def _GetPpiList(self
):
3557 if self
._PpiList
== None:
3558 self
._PpiList
= sdict()
3559 self
._PpiList
.update(self
.Module
.Ppis
)
3560 for Library
in self
.DependentLibraryList
:
3561 self
._PpiList
.update(Library
.Ppis
)
3562 self
.UpdateComments(self
._PpiComments
, Library
.PpiComments
)
3563 self
.UpdateComments(self
._PpiComments
, self
.Module
.PpiComments
)
3564 return self
._PpiList
3566 ## Get the list of include search path
3568 # @retval list The list path
3570 def _GetIncludePathList(self
):
3571 if self
._IncludePathList
== None:
3572 self
._IncludePathList
= []
3573 if self
.AutoGenVersion
< 0x00010005:
3574 for Inc
in self
.Module
.Includes
:
3575 if Inc
not in self
._IncludePathList
:
3576 self
._IncludePathList
.append(Inc
)
3578 Inc
= path
.join(Inc
, self
.Arch
.capitalize())
3579 if os
.path
.exists(Inc
) and Inc
not in self
._IncludePathList
:
3580 self
._IncludePathList
.append(Inc
)
3581 # Edk module needs to put DEBUG_DIR at the end of search path and not to use SOURCE_DIR all the time
3582 self
._IncludePathList
.append(self
.DebugDir
)
3584 self
._IncludePathList
.append(self
.MetaFile
.Dir
)
3585 self
._IncludePathList
.append(self
.DebugDir
)
3587 for Package
in self
.Module
.Packages
:
3588 PackageDir
= mws
.join(self
.WorkspaceDir
, Package
.MetaFile
.Dir
)
3589 if PackageDir
not in self
._IncludePathList
:
3590 self
._IncludePathList
.append(PackageDir
)
3591 IncludesList
= Package
.Includes
3592 if Package
._PrivateIncludes
:
3593 if not self
.MetaFile
.Path
.startswith(PackageDir
):
3594 IncludesList
= list(set(Package
.Includes
).difference(set(Package
._PrivateIncludes
)))
3595 for Inc
in IncludesList
:
3596 if Inc
not in self
._IncludePathList
:
3597 self
._IncludePathList
.append(str(Inc
))
3598 return self
._IncludePathList
3600 def _GetIncludePathLength(self
):
3601 self
._IncludePathLength
= 0
3602 if self
._IncludePathList
:
3603 for inc
in self
._IncludePathList
:
3604 self
._IncludePathLength
+= len(' ' + inc
)
3605 return self
._IncludePathLength
3607 ## Get HII EX PCDs which maybe used by VFR
3609 # efivarstore used by VFR may relate with HII EX PCDs
3610 # Get the variable name and GUID from efivarstore and HII EX PCD
3611 # List the HII EX PCDs in As Built INF if both name and GUID match.
3613 # @retval list HII EX PCDs
3615 def _GetPcdsMaybeUsedByVfr(self
):
3616 if not self
.SourceFileList
:
3620 for SrcFile
in self
.SourceFileList
:
3621 if SrcFile
.Ext
.lower() != '.vfr':
3623 Vfri
= os
.path
.join(self
.OutputDir
, SrcFile
.BaseName
+ '.i')
3624 if not os
.path
.exists(Vfri
):
3626 VfriFile
= open(Vfri
, 'r')
3627 Content
= VfriFile
.read()
3629 Pos
= Content
.find('efivarstore')
3632 # Make sure 'efivarstore' is the start of efivarstore statement
3633 # In case of the value of 'name' (name = efivarstore) is equal to 'efivarstore'
3636 while Index
>= 0 and Content
[Index
] in ' \t\r\n':
3638 if Index
>= 0 and Content
[Index
] != ';':
3639 Pos
= Content
.find('efivarstore', Pos
+ len('efivarstore'))
3642 # 'efivarstore' must be followed by name and guid
3644 Name
= gEfiVarStoreNamePattern
.search(Content
, Pos
)
3647 Guid
= gEfiVarStoreGuidPattern
.search(Content
, Pos
)
3650 NameArray
= ConvertStringToByteArray('L"' + Name
.group(1) + '"')
3651 NameGuids
.append((NameArray
, GuidStructureStringToGuidString(Guid
.group(1))))
3652 Pos
= Content
.find('efivarstore', Name
.end())
3656 for Pcd
in self
.PlatformInfo
.Platform
.Pcds
.values():
3657 if Pcd
.Type
!= TAB_PCDS_DYNAMIC_EX_HII
:
3659 for SkuName
in Pcd
.SkuInfoList
:
3660 SkuInfo
= Pcd
.SkuInfoList
[SkuName
]
3661 Name
= ConvertStringToByteArray(SkuInfo
.VariableName
)
3662 Value
= GuidValue(SkuInfo
.VariableGuid
, self
.PlatformInfo
.PackageList
, self
.MetaFile
.Path
)
3665 Guid
= GuidStructureStringToGuidString(Value
)
3666 if (Name
, Guid
) in NameGuids
and Pcd
not in HiiExPcds
:
3667 HiiExPcds
.append(Pcd
)
3672 def _GenOffsetBin(self
):
3674 for SourceFile
in self
.Module
.Sources
:
3675 if SourceFile
.Type
.upper() == ".VFR" :
3677 # search the .map file to find the offset of vfr binary in the PE32+/TE file.
3679 VfrUniBaseName
[SourceFile
.BaseName
] = (SourceFile
.BaseName
+ "Bin")
3680 if SourceFile
.Type
.upper() == ".UNI" :
3682 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
3684 VfrUniBaseName
["UniOffsetName"] = (self
.Name
+ "Strings")
3686 if len(VfrUniBaseName
) == 0:
3688 MapFileName
= os
.path
.join(self
.OutputDir
, self
.Name
+ ".map")
3689 EfiFileName
= os
.path
.join(self
.OutputDir
, self
.Name
+ ".efi")
3690 VfrUniOffsetList
= GetVariableOffset(MapFileName
, EfiFileName
, VfrUniBaseName
.values())
3691 if not VfrUniOffsetList
:
3694 OutputName
= '%sOffset.bin' % self
.Name
3695 UniVfrOffsetFileName
= os
.path
.join( self
.OutputDir
, OutputName
)
3698 fInputfile
= open(UniVfrOffsetFileName
, "wb+", 0)
3700 EdkLogger
.error("build", FILE_OPEN_FAILURE
, "File open failed for %s" % UniVfrOffsetFileName
,None)
3702 # Use a instance of StringIO to cache data
3703 fStringIO
= StringIO('')
3705 for Item
in VfrUniOffsetList
:
3706 if (Item
[0].find("Strings") != -1):
3708 # UNI offset in image.
3710 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }
3712 UniGuid
= [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66]
3713 UniGuid
= [chr(ItemGuid
) for ItemGuid
in UniGuid
]
3714 fStringIO
.write(''.join(UniGuid
))
3715 UniValue
= pack ('Q', int (Item
[1], 16))
3716 fStringIO
.write (UniValue
)
3719 # VFR binary offset in image.
3721 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };
3723 VfrGuid
= [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2]
3724 VfrGuid
= [chr(ItemGuid
) for ItemGuid
in VfrGuid
]
3725 fStringIO
.write(''.join(VfrGuid
))
3727 VfrValue
= pack ('Q', int (Item
[1], 16))
3728 fStringIO
.write (VfrValue
)
3730 # write data into file.
3733 fInputfile
.write (fStringIO
.getvalue())
3735 EdkLogger
.error("build", FILE_WRITE_FAILURE
, "Write data to file %s failed, please check whether the "
3736 "file been locked or using by other applications." %UniVfrOffsetFileName
,None)
3742 ## Create AsBuilt INF file the module
3744 def CreateAsBuiltInf(self
):
3745 if self
.IsAsBuiltInfCreated
:
3748 # Skip the following code for EDK I inf
3749 if self
.AutoGenVersion
< 0x00010005:
3752 # Skip the following code for libraries
3756 # Skip the following code for modules with no source files
3757 if self
.SourceFileList
== None or self
.SourceFileList
== []:
3760 # Skip the following code for modules without any binary files
3761 if self
.BinaryFileList
<> None and self
.BinaryFileList
<> []:
3764 ### TODO: How to handles mixed source and binary modules
3766 # Find all DynamicEx and PatchableInModule PCDs used by this module and dependent libraries
3767 # Also find all packages that the DynamicEx PCDs depend on
3772 PcdTokenSpaceList
= []
3773 for Pcd
in self
.ModulePcdList
+ self
.LibraryPcdList
:
3774 if Pcd
.Type
== TAB_PCDS_PATCHABLE_IN_MODULE
:
3775 PatchablePcds
+= [Pcd
]
3776 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, 'PatchableInModule'))
3777 elif Pcd
.Type
in GenC
.gDynamicExPcd
:
3780 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, 'DynamicEx'))
3781 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, 'Dynamic'))
3782 PcdTokenSpaceList
.append(Pcd
.TokenSpaceGuidCName
)
3784 GuidList
.update(self
.GuidList
)
3785 for TokenSpace
in self
.GetGuidsUsedByPcd():
3786 # If token space is not referred by patch PCD or Ex PCD, remove the GUID from GUID list
3787 # The GUIDs in GUIDs section should really be the GUIDs in source INF or referred by Ex an patch PCDs
3788 if TokenSpace
not in PcdTokenSpaceList
and TokenSpace
in GuidList
:
3789 GuidList
.pop(TokenSpace
)
3790 CheckList
= (GuidList
, self
.PpiList
, self
.ProtocolList
, PcdCheckList
)
3791 for Package
in self
.DerivedPackageList
:
3792 if Package
in Packages
:
3794 BeChecked
= (Package
.Guids
, Package
.Ppis
, Package
.Protocols
, Package
.Pcds
)
3796 for Index
in range(len(BeChecked
)):
3797 for Item
in CheckList
[Index
]:
3798 if Item
in BeChecked
[Index
]:
3799 Packages
+= [Package
]
3804 VfrPcds
= self
._GetPcdsMaybeUsedByVfr
()
3805 for Pkg
in self
.PlatformInfo
.PackageList
:
3808 for VfrPcd
in VfrPcds
:
3809 if ((VfrPcd
.TokenCName
, VfrPcd
.TokenSpaceGuidCName
, 'DynamicEx') in Pkg
.Pcds
or
3810 (VfrPcd
.TokenCName
, VfrPcd
.TokenSpaceGuidCName
, 'Dynamic') in Pkg
.Pcds
):
3814 ModuleType
= self
.ModuleType
3815 if ModuleType
== 'UEFI_DRIVER' and self
.DepexGenerated
:
3816 ModuleType
= 'DXE_DRIVER'
3819 if self
.PcdIsDriver
!= '':
3820 DriverType
= self
.PcdIsDriver
3823 MDefs
= self
.Module
.Defines
3826 'module_name' : self
.Name
,
3827 'module_guid' : Guid
,
3828 'module_module_type' : ModuleType
,
3829 'module_version_string' : [MDefs
['VERSION_STRING']] if 'VERSION_STRING' in MDefs
else [],
3830 'pcd_is_driver_string' : [],
3831 'module_uefi_specification_version' : [],
3832 'module_pi_specification_version' : [],
3833 'module_entry_point' : self
.Module
.ModuleEntryPointList
,
3834 'module_unload_image' : self
.Module
.ModuleUnloadImageList
,
3835 'module_constructor' : self
.Module
.ConstructorList
,
3836 'module_destructor' : self
.Module
.DestructorList
,
3837 'module_shadow' : [MDefs
['SHADOW']] if 'SHADOW' in MDefs
else [],
3838 'module_pci_vendor_id' : [MDefs
['PCI_VENDOR_ID']] if 'PCI_VENDOR_ID' in MDefs
else [],
3839 'module_pci_device_id' : [MDefs
['PCI_DEVICE_ID']] if 'PCI_DEVICE_ID' in MDefs
else [],
3840 'module_pci_class_code' : [MDefs
['PCI_CLASS_CODE']] if 'PCI_CLASS_CODE' in MDefs
else [],
3841 'module_pci_revision' : [MDefs
['PCI_REVISION']] if 'PCI_REVISION' in MDefs
else [],
3842 'module_build_number' : [MDefs
['BUILD_NUMBER']] if 'BUILD_NUMBER' in MDefs
else [],
3843 'module_spec' : [MDefs
['SPEC']] if 'SPEC' in MDefs
else [],
3844 'module_uefi_hii_resource_section' : [MDefs
['UEFI_HII_RESOURCE_SECTION']] if 'UEFI_HII_RESOURCE_SECTION' in MDefs
else [],
3845 'module_uni_file' : [MDefs
['MODULE_UNI_FILE']] if 'MODULE_UNI_FILE' in MDefs
else [],
3846 'module_arch' : self
.Arch
,
3847 'package_item' : ['%s' % (Package
.MetaFile
.File
.replace('\\', '/')) for Package
in Packages
],
3849 'patchablepcd_item' : [],
3851 'protocol_item' : [],
3855 'libraryclasses_item' : []
3858 if self
.AutoGenVersion
> int(gInfSpecVersion
, 0):
3859 AsBuiltInfDict
['module_inf_version'] = '0x%08x' % self
.AutoGenVersion
3861 AsBuiltInfDict
['module_inf_version'] = gInfSpecVersion
3864 AsBuiltInfDict
['pcd_is_driver_string'] += [DriverType
]
3866 if 'UEFI_SPECIFICATION_VERSION' in self
.Specification
:
3867 AsBuiltInfDict
['module_uefi_specification_version'] += [self
.Specification
['UEFI_SPECIFICATION_VERSION']]
3868 if 'PI_SPECIFICATION_VERSION' in self
.Specification
:
3869 AsBuiltInfDict
['module_pi_specification_version'] += [self
.Specification
['PI_SPECIFICATION_VERSION']]
3871 OutputDir
= self
.OutputDir
.replace('\\', '/').strip('/')
3873 for Item
in self
.CodaTargetList
:
3874 File
= Item
.Target
.Path
.replace('\\', '/').strip('/').replace(OutputDir
, '').strip('/')
3875 if Item
.Target
.Ext
.lower() == '.aml':
3876 AsBuiltInfDict
['binary_item'] += ['ASL|' + File
]
3877 elif Item
.Target
.Ext
.lower() == '.acpi':
3878 AsBuiltInfDict
['binary_item'] += ['ACPI|' + File
]
3879 elif Item
.Target
.Ext
.lower() == '.efi':
3880 AsBuiltInfDict
['binary_item'] += ['PE32|' + self
.Name
+ '.efi']
3882 AsBuiltInfDict
['binary_item'] += ['BIN|' + File
]
3883 if self
.DepexGenerated
:
3884 if self
.ModuleType
in ['PEIM']:
3885 AsBuiltInfDict
['binary_item'] += ['PEI_DEPEX|' + self
.Name
+ '.depex']
3886 if self
.ModuleType
in ['DXE_DRIVER', 'DXE_RUNTIME_DRIVER', 'DXE_SAL_DRIVER', 'UEFI_DRIVER']:
3887 AsBuiltInfDict
['binary_item'] += ['DXE_DEPEX|' + self
.Name
+ '.depex']
3888 if self
.ModuleType
in ['DXE_SMM_DRIVER']:
3889 AsBuiltInfDict
['binary_item'] += ['SMM_DEPEX|' + self
.Name
+ '.depex']
3891 Bin
= self
._GenOffsetBin
()
3893 AsBuiltInfDict
['binary_item'] += ['BIN|%s' % Bin
]
3895 for Root
, Dirs
, Files
in os
.walk(OutputDir
):
3897 if File
.lower().endswith('.pdb'):
3898 AsBuiltInfDict
['binary_item'] += ['DISPOSABLE|' + File
]
3899 HeaderComments
= self
.Module
.HeaderComments
3901 for Index
in range(len(HeaderComments
)):
3902 if HeaderComments
[Index
].find('@BinaryHeader') != -1:
3903 HeaderComments
[Index
] = HeaderComments
[Index
].replace('@BinaryHeader', '@file')
3906 AsBuiltInfDict
['header_comments'] = '\n'.join(HeaderComments
[StartPos
:]).replace(':#', '://')
3907 AsBuiltInfDict
['tail_comments'] = '\n'.join(self
.Module
.TailComments
)
3910 (self
.ProtocolList
, self
._ProtocolComments
, 'protocol_item'),
3911 (self
.PpiList
, self
._PpiComments
, 'ppi_item'),
3912 (GuidList
, self
._GuidComments
, 'guid_item')
3914 for Item
in GenList
:
3915 for CName
in Item
[0]:
3917 if CName
in Item
[1]:
3918 Comments
= '\n '.join(Item
[1][CName
])
3921 Entry
= Comments
+ '\n ' + CName
3922 AsBuiltInfDict
[Item
[2]].append(Entry
)
3923 PatchList
= parsePcdInfoFromMapFile(
3924 os
.path
.join(self
.OutputDir
, self
.Name
+ '.map'),
3925 os
.path
.join(self
.OutputDir
, self
.Name
+ '.efi')
3928 for Pcd
in PatchablePcds
:
3929 TokenCName
= Pcd
.TokenCName
3930 for PcdItem
in GlobalData
.MixedPcd
:
3931 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
3932 TokenCName
= PcdItem
[0]
3934 for PatchPcd
in PatchList
:
3935 if TokenCName
== PatchPcd
[0]:
3940 if Pcd
.DatumType
== 'BOOLEAN':
3941 BoolValue
= Pcd
.DefaultValue
.upper()
3942 if BoolValue
== 'TRUE':
3943 Pcd
.DefaultValue
= '1'
3944 elif BoolValue
== 'FALSE':
3945 Pcd
.DefaultValue
= '0'
3947 if Pcd
.DatumType
!= 'VOID*':
3948 HexFormat
= '0x%02x'
3949 if Pcd
.DatumType
== 'UINT16':
3950 HexFormat
= '0x%04x'
3951 elif Pcd
.DatumType
== 'UINT32':
3952 HexFormat
= '0x%08x'
3953 elif Pcd
.DatumType
== 'UINT64':
3954 HexFormat
= '0x%016x'
3955 PcdValue
= HexFormat
% int(Pcd
.DefaultValue
, 0)
3957 if Pcd
.MaxDatumSize
== None or Pcd
.MaxDatumSize
== '':
3958 EdkLogger
.error("build", AUTOGEN_ERROR
,
3959 "Unknown [MaxDatumSize] of PCD [%s.%s]" % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
3961 ArraySize
= int(Pcd
.MaxDatumSize
, 0)
3962 PcdValue
= Pcd
.DefaultValue
3963 if PcdValue
[0] != '{':
3965 if PcdValue
[0] == 'L':
3967 PcdValue
= PcdValue
.lstrip('L')
3968 PcdValue
= eval(PcdValue
)
3970 for Index
in range(0, len(PcdValue
)):
3972 CharVal
= ord(PcdValue
[Index
])
3973 NewValue
= NewValue
+ '0x%02x' % (CharVal
& 0x00FF) + ', ' \
3974 + '0x%02x' % (CharVal
>> 8) + ', '
3976 NewValue
= NewValue
+ '0x%02x' % (ord(PcdValue
[Index
]) % 0x100) + ', '
3979 Padding
= Padding
* 2
3980 ArraySize
= ArraySize
/ 2
3981 if ArraySize
< (len(PcdValue
) + 1):
3982 EdkLogger
.error("build", AUTOGEN_ERROR
,
3983 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
3985 if ArraySize
> len(PcdValue
) + 1:
3986 NewValue
= NewValue
+ Padding
* (ArraySize
- len(PcdValue
) - 1)
3987 PcdValue
= NewValue
+ Padding
.strip().rstrip(',') + '}'
3988 elif len(PcdValue
.split(',')) <= ArraySize
:
3989 PcdValue
= PcdValue
.rstrip('}') + ', 0x00' * (ArraySize
- len(PcdValue
.split(',')))
3992 EdkLogger
.error("build", AUTOGEN_ERROR
,
3993 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
3995 PcdItem
= '%s.%s|%s|0x%X' % \
3996 (Pcd
.TokenSpaceGuidCName
, TokenCName
, PcdValue
, PatchPcd
[1])
3998 if (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in self
._PcdComments
:
3999 PcdComments
= '\n '.join(self
._PcdComments
[Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
])
4001 PcdItem
= PcdComments
+ '\n ' + PcdItem
4002 AsBuiltInfDict
['patchablepcd_item'].append(PcdItem
)
4005 for Pcd
in Pcds
+ VfrPcds
:
4010 TokenCName
= Pcd
.TokenCName
4011 for PcdItem
in GlobalData
.MixedPcd
:
4012 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
4013 TokenCName
= PcdItem
[0]
4015 if Pcd
.Type
== TAB_PCDS_DYNAMIC_EX_HII
:
4016 for SkuName
in Pcd
.SkuInfoList
:
4017 SkuInfo
= Pcd
.SkuInfoList
[SkuName
]
4018 SkuId
= SkuInfo
.SkuId
4019 HiiInfo
= '## %s|%s|%s' % (SkuInfo
.VariableName
, SkuInfo
.VariableGuid
, SkuInfo
.VariableOffset
)
4023 # Don't generate duplicated HII PCD
4025 if (SkuId
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in HiiPcds
:
4028 HiiPcds
.append((SkuId
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
4029 if (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in self
._PcdComments
:
4030 PcdCommentList
= self
._PcdComments
[Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
][:]
4034 for Index
, Comment
in enumerate(PcdCommentList
):
4035 for Usage
in UsageList
:
4036 if Comment
.find(Usage
) != -1:
4040 if UsageIndex
!= -1:
4041 PcdCommentList
[UsageIndex
] = '## %s %s %s' % (UsageStr
, HiiInfo
, PcdCommentList
[UsageIndex
].replace(UsageStr
, ''))
4043 PcdCommentList
.append('## UNDEFINED ' + HiiInfo
)
4044 PcdComments
= '\n '.join(PcdCommentList
)
4045 PcdEntry
= Pcd
.TokenSpaceGuidCName
+ '.' + TokenCName
4047 PcdEntry
= PcdComments
+ '\n ' + PcdEntry
4048 AsBuiltInfDict
['pcd_item'] += [PcdEntry
]
4049 for Item
in self
.BuildOption
:
4050 if 'FLAGS' in self
.BuildOption
[Item
]:
4051 AsBuiltInfDict
['flags_item'] += ['%s:%s_%s_%s_%s_FLAGS = %s' % (self
.ToolChainFamily
, self
.BuildTarget
, self
.ToolChain
, self
.Arch
, Item
, self
.BuildOption
[Item
]['FLAGS'].strip())]
4053 # Generated LibraryClasses section in comments.
4054 for Library
in self
.LibraryAutoGenList
:
4055 AsBuiltInfDict
['libraryclasses_item'] += [Library
.MetaFile
.File
.replace('\\', '/')]
4057 # Generated depex expression section in comments.
4058 AsBuiltInfDict
['depexsection_item'] = ''
4059 DepexExpresion
= self
._GetDepexExpresionString
()
4061 AsBuiltInfDict
['depexsection_item'] = DepexExpresion
4063 AsBuiltInf
= TemplateString()
4064 AsBuiltInf
.Append(gAsBuiltInfHeaderString
.Replace(AsBuiltInfDict
))
4066 SaveFileOnChange(os
.path
.join(self
.OutputDir
, self
.Name
+ '.inf'), str(AsBuiltInf
), False)
4068 self
.IsAsBuiltInfCreated
= True
4070 ## Create makefile for the module and its dependent libraries
4072 # @param CreateLibraryMakeFile Flag indicating if or not the makefiles of
4073 # dependent libraries will be created
4075 def CreateMakeFile(self
, CreateLibraryMakeFile
=True):
4076 # Ignore generating makefile when it is a binary module
4077 if self
.IsBinaryModule
:
4080 if self
.IsMakeFileCreated
:
4085 if not self
.IsLibrary
and CreateLibraryMakeFile
:
4086 for LibraryAutoGen
in self
.LibraryAutoGenList
:
4087 LibraryAutoGen
.CreateMakeFile()
4089 if len(self
.CustomMakefile
) == 0:
4090 Makefile
= GenMake
.ModuleMakefile(self
)
4092 Makefile
= GenMake
.CustomMakefile(self
)
4093 if Makefile
.Generate():
4094 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated makefile for module %s [%s]" %
4095 (self
.Name
, self
.Arch
))
4097 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of makefile for module %s [%s]" %
4098 (self
.Name
, self
.Arch
))
4100 self
.CreateTimeStamp(Makefile
)
4101 self
.IsMakeFileCreated
= True
4103 def CopyBinaryFiles(self
):
4104 for File
in self
.Module
.Binaries
:
4106 DstPath
= os
.path
.join(self
.OutputDir
, os
.path
.basename(SrcPath
))
4107 CopyLongFilePath(SrcPath
, DstPath
)
4108 ## Create autogen code for the module and its dependent libraries
4110 # @param CreateLibraryCodeFile Flag indicating if or not the code of
4111 # dependent libraries will be created
4113 def CreateCodeFile(self
, CreateLibraryCodeFile
=True):
4114 if self
.IsCodeFileCreated
:
4119 # Need to generate PcdDatabase even PcdDriver is binarymodule
4120 if self
.IsBinaryModule
and self
.PcdIsDriver
!= '':
4121 CreatePcdDatabaseCode(self
, TemplateString(), TemplateString())
4123 if self
.IsBinaryModule
:
4125 self
.CopyBinaryFiles()
4128 if not self
.IsLibrary
and CreateLibraryCodeFile
:
4129 for LibraryAutoGen
in self
.LibraryAutoGenList
:
4130 LibraryAutoGen
.CreateCodeFile()
4133 IgoredAutoGenList
= []
4135 for File
in self
.AutoGenFileList
:
4136 if GenC
.Generate(File
.Path
, self
.AutoGenFileList
[File
], File
.IsBinary
):
4137 #Ignore Edk AutoGen.c
4138 if self
.AutoGenVersion
< 0x00010005 and File
.Name
== 'AutoGen.c':
4141 AutoGenList
.append(str(File
))
4143 IgoredAutoGenList
.append(str(File
))
4145 # Skip the following code for EDK I inf
4146 if self
.AutoGenVersion
< 0x00010005:
4149 for ModuleType
in self
.DepexList
:
4150 # Ignore empty [depex] section or [depex] section for "USER_DEFINED" module
4151 if len(self
.DepexList
[ModuleType
]) == 0 or ModuleType
== "USER_DEFINED":
4154 Dpx
= GenDepex
.DependencyExpression(self
.DepexList
[ModuleType
], ModuleType
, True)
4155 DpxFile
= gAutoGenDepexFileName
% {"module_name" : self
.Name
}
4157 if len(Dpx
.PostfixNotation
) <> 0:
4158 self
.DepexGenerated
= True
4160 if Dpx
.Generate(path
.join(self
.OutputDir
, DpxFile
)):
4161 AutoGenList
.append(str(DpxFile
))
4163 IgoredAutoGenList
.append(str(DpxFile
))
4165 if IgoredAutoGenList
== []:
4166 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] files for module %s [%s]" %
4167 (" ".join(AutoGenList
), self
.Name
, self
.Arch
))
4168 elif AutoGenList
== []:
4169 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of [%s] files for module %s [%s]" %
4170 (" ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
4172 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] (skipped %s) files for module %s [%s]" %
4173 (" ".join(AutoGenList
), " ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
4175 self
.IsCodeFileCreated
= True
4178 ## Summarize the ModuleAutoGen objects of all libraries used by this module
4179 def _GetLibraryAutoGenList(self
):
4180 if self
._LibraryAutoGenList
== None:
4181 self
._LibraryAutoGenList
= []
4182 for Library
in self
.DependentLibraryList
:
4189 self
.PlatformInfo
.MetaFile
4191 if La
not in self
._LibraryAutoGenList
:
4192 self
._LibraryAutoGenList
.append(La
)
4193 for Lib
in La
.CodaTargetList
:
4194 self
._ApplyBuildRule
(Lib
.Target
, TAB_UNKNOWN_FILE
)
4195 return self
._LibraryAutoGenList
4197 ## Decide whether we can skip the ModuleAutoGen process
4198 # If any source file is newer than the modeule than we cannot skip
4201 if not os
.path
.exists(self
.GetTimeStampPath()):
4203 #last creation time of the module
4204 DstTimeStamp
= os
.stat(self
.GetTimeStampPath())[8]
4206 SrcTimeStamp
= self
.Workspace
._SrcTimeStamp
4207 if SrcTimeStamp
> DstTimeStamp
:
4210 with
open(self
.GetTimeStampPath(),'r') as f
:
4212 source
= source
.rstrip('\n')
4213 if source
not in ModuleAutoGen
.TimeDict
:
4214 ModuleAutoGen
.TimeDict
[source
] = os
.stat(source
)[8]
4215 if ModuleAutoGen
.TimeDict
[source
] > DstTimeStamp
:
4219 def GetTimeStampPath(self
):
4220 if self
._TimeStampPath
== None:
4221 self
._TimeStampPath
= os
.path
.join(self
.MakeFileDir
, 'AutoGenTimeStamp')
4222 return self
._TimeStampPath
4223 def CreateTimeStamp(self
, Makefile
):
4227 FileSet
.add (self
.MetaFile
.Path
)
4229 for SourceFile
in self
.Module
.Sources
:
4230 FileSet
.add (SourceFile
.Path
)
4232 for Lib
in self
.DependentLibraryList
:
4233 FileSet
.add (Lib
.MetaFile
.Path
)
4235 for f
in self
.AutoGenDepSet
:
4236 FileSet
.add (f
.Path
)
4238 if os
.path
.exists (self
.GetTimeStampPath()):
4239 os
.remove (self
.GetTimeStampPath())
4240 with
open(self
.GetTimeStampPath(), 'w+') as file:
4244 Module
= property(_GetModule
)
4245 Name
= property(_GetBaseName
)
4246 Guid
= property(_GetGuid
)
4247 Version
= property(_GetVersion
)
4248 ModuleType
= property(_GetModuleType
)
4249 ComponentType
= property(_GetComponentType
)
4250 BuildType
= property(_GetBuildType
)
4251 PcdIsDriver
= property(_GetPcdIsDriver
)
4252 AutoGenVersion
= property(_GetAutoGenVersion
)
4253 Macros
= property(_GetMacros
)
4254 Specification
= property(_GetSpecification
)
4256 IsLibrary
= property(_IsLibrary
)
4257 IsBinaryModule
= property(_IsBinaryModule
)
4258 BuildDir
= property(_GetBuildDir
)
4259 OutputDir
= property(_GetOutputDir
)
4260 DebugDir
= property(_GetDebugDir
)
4261 MakeFileDir
= property(_GetMakeFileDir
)
4262 CustomMakefile
= property(_GetCustomMakefile
)
4264 IncludePathList
= property(_GetIncludePathList
)
4265 IncludePathLength
= property(_GetIncludePathLength
)
4266 AutoGenFileList
= property(_GetAutoGenFileList
)
4267 UnicodeFileList
= property(_GetUnicodeFileList
)
4268 VfrFileList
= property(_GetVfrFileList
)
4269 SourceFileList
= property(_GetSourceFileList
)
4270 BinaryFileList
= property(_GetBinaryFiles
) # FileType : [File List]
4271 Targets
= property(_GetTargets
)
4272 IntroTargetList
= property(_GetIntroTargetList
)
4273 CodaTargetList
= property(_GetFinalTargetList
)
4274 FileTypes
= property(_GetFileTypes
)
4275 BuildRules
= property(_GetBuildRules
)
4276 IdfFileList
= property(_GetIdfFileList
)
4278 DependentPackageList
= property(_GetDependentPackageList
)
4279 DependentLibraryList
= property(_GetLibraryList
)
4280 LibraryAutoGenList
= property(_GetLibraryAutoGenList
)
4281 DerivedPackageList
= property(_GetDerivedPackageList
)
4283 ModulePcdList
= property(_GetModulePcdList
)
4284 LibraryPcdList
= property(_GetLibraryPcdList
)
4285 GuidList
= property(_GetGuidList
)
4286 ProtocolList
= property(_GetProtocolList
)
4287 PpiList
= property(_GetPpiList
)
4288 DepexList
= property(_GetDepexTokenList
)
4289 DxsFile
= property(_GetDxsFile
)
4290 DepexExpressionList
= property(_GetDepexExpressionTokenList
)
4291 BuildOption
= property(_GetModuleBuildOption
)
4292 BuildOptionIncPathList
= property(_GetBuildOptionIncPathList
)
4293 BuildCommand
= property(_GetBuildCommand
)
4295 FixedAtBuildPcds
= property(_GetFixedAtBuildPcds
)
4297 # This acts like the main() function for the script, unless it is 'import'ed into another script.
4298 if __name__
== '__main__':