2 # Generate AutoGen.h, AutoGen.c and *.depex files
4 # Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
5 # This program and the accompanying materials
6 # are licensed and made available under the terms and conditions of the BSD License
7 # which accompanies this distribution. The full text of the license may be found at
8 # http://opensource.org/licenses/bsd-license.php
10 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 import Common
.LongFilePathOs
as os
18 import os
.path
as path
25 from StringIO
import StringIO
27 from StrGather
import *
28 from BuildEngine
import BuildRule
30 from Common
.LongFilePathSupport
import CopyLongFilePath
31 from Common
.BuildToolError
import *
32 from Common
.DataType
import *
33 from Common
.Misc
import *
34 from Common
.String
import *
35 import Common
.GlobalData
as GlobalData
36 from GenFds
.FdfParser
import *
37 from CommonDataClass
.CommonClass
import SkuInfoClass
38 from Workspace
.BuildClassObject
import *
39 from GenPatchPcdTable
.GenPatchPcdTable
import parsePcdInfoFromMapFile
40 import Common
.VpdInfoFile
as VpdInfoFile
41 from GenPcdDb
import CreatePcdDatabaseCode
42 from Workspace
.MetaFileCommentParser
import UsageList
43 from Common
.MultipleWorkspace
import MultipleWorkspace
as mws
44 import InfSectionParser
47 from GenVar
import VariableMgr
,var_info
48 from collections
import OrderedDict
50 ## Regular expression for splitting Dependency Expression string into tokens
51 gDepexTokenPattern
= re
.compile("(\(|\)|\w+| \S+\.inf)")
53 ## Regular expression for match: PCD(xxxx.yyy)
54 gPCDAsGuidPattern
= re
.compile(r
"^PCD\(.+\..+\)$")
57 # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
58 # is the former use /I , the Latter used -I to specify include directories
60 gBuildOptIncludePatternMsft
= re
.compile(r
"(?:.*?)/I[ \t]*([^ ]*)", re
.MULTILINE | re
.DOTALL
)
61 gBuildOptIncludePatternOther
= re
.compile(r
"(?:.*?)-I[ \t]*([^ ]*)", re
.MULTILINE | re
.DOTALL
)
64 # Match name = variable
66 gEfiVarStoreNamePattern
= re
.compile("\s*name\s*=\s*(\w+)")
68 # The format of guid in efivarstore statement likes following and must be correct:
69 # guid = {0xA04A27f4, 0xDF00, 0x4D42, {0xB5, 0x52, 0x39, 0x51, 0x13, 0x02, 0x11, 0x3D}}
71 gEfiVarStoreGuidPattern
= re
.compile("\s*guid\s*=\s*({.*?{.*?}\s*})")
73 ## Mapping Makefile type
74 gMakeTypeMap
= {"MSFT":"nmake", "GCC":"gmake"}
77 ## Build rule configuration file
78 gDefaultBuildRuleFile
= 'build_rule.txt'
80 ## Tools definition configuration file
81 gDefaultToolsDefFile
= 'tools_def.txt'
83 ## Build rule default version
84 AutoGenReqBuildRuleVerNum
= "0.1"
86 ## default file name for AutoGen
87 gAutoGenCodeFileName
= "AutoGen.c"
88 gAutoGenHeaderFileName
= "AutoGen.h"
89 gAutoGenStringFileName
= "%(module_name)sStrDefs.h"
90 gAutoGenStringFormFileName
= "%(module_name)sStrDefs.hpk"
91 gAutoGenDepexFileName
= "%(module_name)s.depex"
92 gAutoGenImageDefFileName
= "%(module_name)sImgDefs.h"
93 gAutoGenIdfFileName
= "%(module_name)sIdf.hpk"
94 gInfSpecVersion
= "0x00010017"
97 # Template string to generic AsBuilt INF
99 gAsBuiltInfHeaderString
= TemplateString("""${header_comments}
102 # FILE auto-generated
105 INF_VERSION = ${module_inf_version}
106 BASE_NAME = ${module_name}
107 FILE_GUID = ${module_guid}
108 MODULE_TYPE = ${module_module_type}${BEGIN}
109 VERSION_STRING = ${module_version_string}${END}${BEGIN}
110 PCD_IS_DRIVER = ${pcd_is_driver_string}${END}${BEGIN}
111 UEFI_SPECIFICATION_VERSION = ${module_uefi_specification_version}${END}${BEGIN}
112 PI_SPECIFICATION_VERSION = ${module_pi_specification_version}${END}${BEGIN}
113 ENTRY_POINT = ${module_entry_point}${END}${BEGIN}
114 UNLOAD_IMAGE = ${module_unload_image}${END}${BEGIN}
115 CONSTRUCTOR = ${module_constructor}${END}${BEGIN}
116 DESTRUCTOR = ${module_destructor}${END}${BEGIN}
117 SHADOW = ${module_shadow}${END}${BEGIN}
118 PCI_VENDOR_ID = ${module_pci_vendor_id}${END}${BEGIN}
119 PCI_DEVICE_ID = ${module_pci_device_id}${END}${BEGIN}
120 PCI_CLASS_CODE = ${module_pci_class_code}${END}${BEGIN}
121 PCI_REVISION = ${module_pci_revision}${END}${BEGIN}
122 BUILD_NUMBER = ${module_build_number}${END}${BEGIN}
123 SPEC = ${module_spec}${END}${BEGIN}
124 UEFI_HII_RESOURCE_SECTION = ${module_uefi_hii_resource_section}${END}${BEGIN}
125 MODULE_UNI_FILE = ${module_uni_file}${END}
127 [Packages.${module_arch}]${BEGIN}
128 ${package_item}${END}
130 [Binaries.${module_arch}]${BEGIN}
133 [PatchPcd.${module_arch}]${BEGIN}
137 [Protocols.${module_arch}]${BEGIN}
141 [Ppis.${module_arch}]${BEGIN}
145 [Guids.${module_arch}]${BEGIN}
149 [PcdEx.${module_arch}]${BEGIN}
153 [LibraryClasses.${module_arch}]
154 ## @LIB_INSTANCES${BEGIN}
155 # ${libraryclasses_item}${END}
159 ${userextension_tianocore_item}
163 [BuildOptions.${module_arch}]
165 ## ${flags_item}${END}
168 ## Base class for AutoGen
170 # This class just implements the cache mechanism of AutoGen objects.
172 class AutoGen(object):
173 # database to maintain the objects in each child class
174 __ObjectCache
= {} # (BuildTarget, ToolChain, ARCH, platform file): AutoGen object
178 # @param Class class object of real AutoGen class
179 # (WorkspaceAutoGen, ModuleAutoGen or PlatformAutoGen)
180 # @param Workspace Workspace directory or WorkspaceAutoGen object
181 # @param MetaFile The path of meta file
182 # @param Target Build target
183 # @param Toolchain Tool chain name
184 # @param Arch Target arch
185 # @param *args The specific class related parameters
186 # @param **kwargs The specific class related dict parameters
188 def __new__(cls
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
189 # check if the object has been created
190 Key
= (Target
, Toolchain
, Arch
, MetaFile
)
192 # if it exists, just return it directly
193 return cls
.__ObjectCache
[Key
]
195 # it didnt exist. create it, cache it, then return it
196 cls
.__ObjectCache
[Key
] = super(AutoGen
, cls
).__new
__(cls
)
197 return cls
.__ObjectCache
[Key
]
199 def __init__ (self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
200 super(AutoGen
, self
).__init
__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
204 # The file path of platform file will be used to represent hash value of this object
206 # @retval int Hash value of the file path of platform file
209 return hash(self
.MetaFile
)
213 # The file path of platform file will be used to represent this object
215 # @retval string String of platform file path
218 return str(self
.MetaFile
)
221 def __eq__(self
, Other
):
222 return Other
and self
.MetaFile
== Other
224 ## Workspace AutoGen class
226 # This class is used mainly to control the whole platform build for different
227 # architecture. This class will generate top level makefile.
229 class WorkspaceAutoGen(AutoGen
):
230 # call super().__init__ then call the worker function with different parameter count
231 def __init__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
235 super(WorkspaceAutoGen
, self
).__init
__(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
236 self
._InitWorker
(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
239 ## Initialize WorkspaceAutoGen
241 # @param WorkspaceDir Root directory of workspace
242 # @param ActivePlatform Meta-file of active platform
243 # @param Target Build target
244 # @param Toolchain Tool chain name
245 # @param ArchList List of architecture of current build
246 # @param MetaFileDb Database containing meta-files
247 # @param BuildConfig Configuration of build
248 # @param ToolDefinition Tool chain definitions
249 # @param FlashDefinitionFile File of flash definition
250 # @param Fds FD list to be generated
251 # @param Fvs FV list to be generated
252 # @param Caps Capsule list to be generated
253 # @param SkuId SKU id from command line
255 def _InitWorker(self
, WorkspaceDir
, ActivePlatform
, Target
, Toolchain
, ArchList
, MetaFileDb
,
256 BuildConfig
, ToolDefinition
, FlashDefinitionFile
='', Fds
=None, Fvs
=None, Caps
=None, SkuId
='', UniFlag
=None,
257 Progress
=None, BuildModule
=None):
264 self
.BuildDatabase
= MetaFileDb
265 self
.MetaFile
= ActivePlatform
266 self
.WorkspaceDir
= WorkspaceDir
267 self
.Platform
= self
.BuildDatabase
[self
.MetaFile
, 'COMMON', Target
, Toolchain
]
268 GlobalData
.gActivePlatform
= self
.Platform
269 self
.BuildTarget
= Target
270 self
.ToolChain
= Toolchain
271 self
.ArchList
= ArchList
273 self
.UniFlag
= UniFlag
275 self
.TargetTxt
= BuildConfig
276 self
.ToolDef
= ToolDefinition
277 self
.FdfFile
= FlashDefinitionFile
278 self
.FdTargetList
= Fds
279 self
.FvTargetList
= Fvs
280 self
.CapTargetList
= Caps
281 self
.AutoGenObjectList
= []
282 self
._BuildDir
= None
284 self
._MakeFileDir
= None
285 self
._BuildCommand
= None
288 # there's many relative directory operations, so ...
289 os
.chdir(self
.WorkspaceDir
)
294 if not self
.ArchList
:
295 ArchList
= set(self
.Platform
.SupArchList
)
297 ArchList
= set(self
.ArchList
) & set(self
.Platform
.SupArchList
)
299 EdkLogger
.error("build", PARAMETER_INVALID
,
300 ExtraData
= "Invalid ARCH specified. [Valid ARCH: %s]" % (" ".join(self
.Platform
.SupArchList
)))
301 elif self
.ArchList
and len(ArchList
) != len(self
.ArchList
):
302 SkippedArchList
= set(self
.ArchList
).symmetric_difference(set(self
.Platform
.SupArchList
))
303 EdkLogger
.verbose("\nArch [%s] is ignored because the platform supports [%s] only!"
304 % (" ".join(SkippedArchList
), " ".join(self
.Platform
.SupArchList
)))
305 self
.ArchList
= tuple(ArchList
)
307 # Validate build target
308 if self
.BuildTarget
not in self
.Platform
.BuildTargets
:
309 EdkLogger
.error("build", PARAMETER_INVALID
,
310 ExtraData
="Build target [%s] is not supported by the platform. [Valid target: %s]"
311 % (self
.BuildTarget
, " ".join(self
.Platform
.BuildTargets
)))
314 # parse FDF file to get PCDs in it, if any
316 self
.FdfFile
= self
.Platform
.FlashDefinition
320 EdkLogger
.info('%-16s = %s' % ("Architecture(s)", ' '.join(self
.ArchList
)))
321 EdkLogger
.info('%-16s = %s' % ("Build target", self
.BuildTarget
))
322 EdkLogger
.info('%-16s = %s' % ("Toolchain", self
.ToolChain
))
324 EdkLogger
.info('\n%-24s = %s' % ("Active Platform", self
.Platform
))
326 EdkLogger
.info('%-24s = %s' % ("Active Module", BuildModule
))
329 EdkLogger
.info('%-24s = %s' % ("Flash Image Definition", self
.FdfFile
))
331 EdkLogger
.verbose("\nFLASH_DEFINITION = %s" % self
.FdfFile
)
334 Progress
.Start("\nProcessing meta-data")
338 # Mark now build in AutoGen Phase
340 GlobalData
.gAutoGenPhase
= True
341 Fdf
= FdfParser(self
.FdfFile
.Path
)
343 GlobalData
.gFdfParser
= Fdf
344 GlobalData
.gAutoGenPhase
= False
345 PcdSet
= Fdf
.Profile
.PcdDict
346 if Fdf
.CurrentFdName
and Fdf
.CurrentFdName
in Fdf
.Profile
.FdDict
:
347 FdDict
= Fdf
.Profile
.FdDict
[Fdf
.CurrentFdName
]
348 for FdRegion
in FdDict
.RegionList
:
349 if str(FdRegion
.RegionType
) is 'FILE' and self
.Platform
.VpdToolGuid
in str(FdRegion
.RegionDataList
):
350 if int(FdRegion
.Offset
) % 8 != 0:
351 EdkLogger
.error("build", FORMAT_INVALID
, 'The VPD Base Address %s must be 8-byte aligned.' % (FdRegion
.Offset
))
352 ModuleList
= Fdf
.Profile
.InfList
353 self
.FdfProfile
= Fdf
.Profile
354 for fvname
in self
.FvTargetList
:
355 if fvname
.upper() not in self
.FdfProfile
.FvDict
:
356 EdkLogger
.error("build", OPTION_VALUE_INVALID
,
357 "No such an FV in FDF file: %s" % fvname
)
359 # In DSC file may use FILE_GUID to override the module, then in the Platform.Modules use FILE_GUIDmodule.inf as key,
360 # but the path (self.MetaFile.Path) is the real path
361 for key
in self
.FdfProfile
.InfDict
:
365 for Arch
in self
.ArchList
:
366 Platform_cache
[Arch
] = self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
367 MetaFile_cache
[Arch
] = []
368 for Pkey
in Platform_cache
[Arch
].Modules
.keys():
369 MetaFile_cache
[Arch
].append(Platform_cache
[Arch
].Modules
[Pkey
].MetaFile
)
370 for Inf
in self
.FdfProfile
.InfDict
[key
]:
371 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
372 for Arch
in self
.ArchList
:
373 if ModuleFile
in MetaFile_cache
[Arch
]:
376 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, Target
, Toolchain
]
377 if not ModuleData
.IsBinaryModule
:
378 EdkLogger
.error('build', PARSER_ERROR
, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile
)
381 for Arch
in self
.ArchList
:
383 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
385 for Pkey
in Platform
.Modules
.keys():
386 MetaFileList
.append(Platform
.Modules
[Pkey
].MetaFile
)
387 for Inf
in self
.FdfProfile
.InfDict
[key
]:
388 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
389 if ModuleFile
in MetaFileList
:
391 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, Target
, Toolchain
]
392 if not ModuleData
.IsBinaryModule
:
393 EdkLogger
.error('build', PARSER_ERROR
, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile
)
398 self
.FdfProfile
= None
399 if self
.FdTargetList
:
400 EdkLogger
.info("No flash definition file found. FD [%s] will be ignored." % " ".join(self
.FdTargetList
))
401 self
.FdTargetList
= []
402 if self
.FvTargetList
:
403 EdkLogger
.info("No flash definition file found. FV [%s] will be ignored." % " ".join(self
.FvTargetList
))
404 self
.FvTargetList
= []
405 if self
.CapTargetList
:
406 EdkLogger
.info("No flash definition file found. Capsule [%s] will be ignored." % " ".join(self
.CapTargetList
))
407 self
.CapTargetList
= []
409 # apply SKU and inject PCDs from Flash Definition file
410 for Arch
in self
.ArchList
:
411 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
413 SourcePcdDict
= {'DynamicEx':set(), 'PatchableInModule':set(),'Dynamic':set(),'FixedAtBuild':set()}
414 BinaryPcdDict
= {'DynamicEx':set(), 'PatchableInModule':set()}
415 SourcePcdDict_Keys
= SourcePcdDict
.keys()
416 BinaryPcdDict_Keys
= BinaryPcdDict
.keys()
418 # generate the SourcePcdDict and BinaryPcdDict
419 PGen
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
420 for BuildData
in PGen
.BuildDatabase
._CACHE
_.values():
421 if BuildData
.Arch
!= Arch
:
423 if BuildData
.MetaFile
.Ext
== '.inf':
424 for key
in BuildData
.Pcds
:
425 if BuildData
.Pcds
[key
].Pending
:
426 if key
in Platform
.Pcds
:
427 PcdInPlatform
= Platform
.Pcds
[key
]
428 if PcdInPlatform
.Type
not in [None, '']:
429 BuildData
.Pcds
[key
].Type
= PcdInPlatform
.Type
431 if BuildData
.MetaFile
in Platform
.Modules
:
432 PlatformModule
= Platform
.Modules
[str(BuildData
.MetaFile
)]
433 if key
in PlatformModule
.Pcds
:
434 PcdInPlatform
= PlatformModule
.Pcds
[key
]
435 if PcdInPlatform
.Type
not in [None, '']:
436 BuildData
.Pcds
[key
].Type
= PcdInPlatform
.Type
438 if 'DynamicEx' in BuildData
.Pcds
[key
].Type
:
439 if BuildData
.IsBinaryModule
:
440 BinaryPcdDict
['DynamicEx'].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
442 SourcePcdDict
['DynamicEx'].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
444 elif 'PatchableInModule' in BuildData
.Pcds
[key
].Type
:
445 if BuildData
.MetaFile
.Ext
== '.inf':
446 if BuildData
.IsBinaryModule
:
447 BinaryPcdDict
['PatchableInModule'].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
449 SourcePcdDict
['PatchableInModule'].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
451 elif 'Dynamic' in BuildData
.Pcds
[key
].Type
:
452 SourcePcdDict
['Dynamic'].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
453 elif 'FixedAtBuild' in BuildData
.Pcds
[key
].Type
:
454 SourcePcdDict
['FixedAtBuild'].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
458 # A PCD can only use one type for all source modules
460 for i
in SourcePcdDict_Keys
:
461 for j
in SourcePcdDict_Keys
:
463 Intersections
= SourcePcdDict
[i
].intersection(SourcePcdDict
[j
])
464 if len(Intersections
) > 0:
468 "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
),
469 ExtraData
="%s" % '\n\t'.join([str(P
[1]+'.'+P
[0]) for P
in Intersections
])
473 # intersection the BinaryPCD for Mixed PCD
475 for i
in BinaryPcdDict_Keys
:
476 for j
in BinaryPcdDict_Keys
:
478 Intersections
= BinaryPcdDict
[i
].intersection(BinaryPcdDict
[j
])
479 for item
in Intersections
:
480 NewPcd1
= (item
[0] + '_' + i
, item
[1])
481 NewPcd2
= (item
[0] + '_' + j
, item
[1])
482 if item
not in GlobalData
.MixedPcd
:
483 GlobalData
.MixedPcd
[item
] = [NewPcd1
, NewPcd2
]
485 if NewPcd1
not in GlobalData
.MixedPcd
[item
]:
486 GlobalData
.MixedPcd
[item
].append(NewPcd1
)
487 if NewPcd2
not in GlobalData
.MixedPcd
[item
]:
488 GlobalData
.MixedPcd
[item
].append(NewPcd2
)
491 # intersection the SourcePCD and BinaryPCD for Mixed PCD
493 for i
in SourcePcdDict_Keys
:
494 for j
in BinaryPcdDict_Keys
:
496 Intersections
= SourcePcdDict
[i
].intersection(BinaryPcdDict
[j
])
497 for item
in Intersections
:
498 NewPcd1
= (item
[0] + '_' + i
, item
[1])
499 NewPcd2
= (item
[0] + '_' + j
, item
[1])
500 if item
not in GlobalData
.MixedPcd
:
501 GlobalData
.MixedPcd
[item
] = [NewPcd1
, NewPcd2
]
503 if NewPcd1
not in GlobalData
.MixedPcd
[item
]:
504 GlobalData
.MixedPcd
[item
].append(NewPcd1
)
505 if NewPcd2
not in GlobalData
.MixedPcd
[item
]:
506 GlobalData
.MixedPcd
[item
].append(NewPcd2
)
508 for BuildData
in PGen
.BuildDatabase
._CACHE
_.values():
509 if BuildData
.Arch
!= Arch
:
511 for key
in BuildData
.Pcds
:
512 for SinglePcd
in GlobalData
.MixedPcd
:
513 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) == SinglePcd
:
514 for item
in GlobalData
.MixedPcd
[SinglePcd
]:
515 Pcd_Type
= item
[0].split('_')[-1]
516 if (Pcd_Type
== BuildData
.Pcds
[key
].Type
) or (Pcd_Type
== TAB_PCDS_DYNAMIC_EX
and BuildData
.Pcds
[key
].Type
in GenC
.gDynamicExPcd
) or \
517 (Pcd_Type
== TAB_PCDS_DYNAMIC
and BuildData
.Pcds
[key
].Type
in GenC
.gDynamicPcd
):
518 Value
= BuildData
.Pcds
[key
]
519 Value
.TokenCName
= BuildData
.Pcds
[key
].TokenCName
+ '_' + Pcd_Type
521 newkey
= (Value
.TokenCName
, key
[1])
523 newkey
= (Value
.TokenCName
, key
[1], key
[2])
524 del BuildData
.Pcds
[key
]
525 BuildData
.Pcds
[newkey
] = Value
529 # handle the mixed pcd in FDF file
531 if key
in GlobalData
.MixedPcd
:
534 for item
in GlobalData
.MixedPcd
[key
]:
537 #Collect package set information from INF of FDF
539 for Inf
in ModuleList
:
540 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
541 if ModuleFile
in Platform
.Modules
:
543 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, Target
, Toolchain
]
544 PkgSet
.update(ModuleData
.Packages
)
545 Pkgs
= list(PkgSet
) + list(PGen
.PackageList
)
550 DecPcds
[Pcd
[0], Pcd
[1]] = Pkg
.Pcds
[Pcd
]
551 DecPcdsKey
.add((Pcd
[0], Pcd
[1], Pcd
[2]))
553 Platform
.SkuName
= self
.SkuId
554 for Name
, Guid
in PcdSet
:
555 if (Name
, Guid
) not in DecPcds
:
559 "PCD (%s.%s) used in FDF is not declared in DEC files." % (Guid
, Name
),
560 File
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][0],
561 Line
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][1]
564 # Check whether Dynamic or DynamicEx PCD used in FDF file. If used, build break and give a error message.
565 if (Name
, Guid
, TAB_PCDS_FIXED_AT_BUILD
) in DecPcdsKey \
566 or (Name
, Guid
, TAB_PCDS_PATCHABLE_IN_MODULE
) in DecPcdsKey \
567 or (Name
, Guid
, TAB_PCDS_FEATURE_FLAG
) in DecPcdsKey
:
568 Platform
.AddPcd(Name
, Guid
, PcdSet
[Name
, Guid
])
570 elif (Name
, Guid
, TAB_PCDS_DYNAMIC
) in DecPcdsKey
or (Name
, Guid
, TAB_PCDS_DYNAMIC_EX
) in DecPcdsKey
:
574 "Using Dynamic or DynamicEx type of PCD [%s.%s] in FDF file is not allowed." % (Guid
, Name
),
575 File
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][0],
576 Line
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][1]
579 Pa
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
581 # Explicitly collect platform's dynamic PCDs
583 Pa
.CollectPlatformDynamicPcds()
584 Pa
.CollectFixedAtBuildPcds()
585 self
.AutoGenObjectList
.append(Pa
)
588 # Generate Package level hash value
590 GlobalData
.gPackageHash
[Arch
] = {}
591 if GlobalData
.gUseHashCache
:
593 self
._GenPkgLevelHash
(Pkg
)
596 # Check PCDs token value conflict in each DEC file.
598 self
._CheckAllPcdsTokenValueConflict
()
601 # Check PCD type and definition between DSC and DEC
603 self
._CheckPcdDefineAndType
()
606 # self._CheckDuplicateInFV(Fdf)
609 # Create BuildOptions Macro & PCD metafile, also add the Active Platform and FDF file.
611 content
= 'gCommandLineDefines: '
612 content
+= str(GlobalData
.gCommandLineDefines
)
613 content
+= os
.linesep
614 content
+= 'BuildOptionPcd: '
615 content
+= str(GlobalData
.BuildOptionPcd
)
616 content
+= os
.linesep
617 content
+= 'Active Platform: '
618 content
+= str(self
.Platform
)
619 content
+= os
.linesep
621 content
+= 'Flash Image Definition: '
622 content
+= str(self
.FdfFile
)
623 content
+= os
.linesep
624 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'BuildOptions'), content
, False)
627 # Create PcdToken Number file for Dynamic/DynamicEx Pcd.
629 PcdTokenNumber
= 'PcdTokenNumber: '
630 if Pa
.PcdTokenNumber
:
631 if Pa
.DynamicPcdList
:
632 for Pcd
in Pa
.DynamicPcdList
:
633 PcdTokenNumber
+= os
.linesep
634 PcdTokenNumber
+= str((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
))
635 PcdTokenNumber
+= ' : '
636 PcdTokenNumber
+= str(Pa
.PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
])
637 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'PcdTokenNumber'), PcdTokenNumber
, False)
640 # Get set of workspace metafiles
642 AllWorkSpaceMetaFiles
= self
._GetMetaFiles
(Target
, Toolchain
, Arch
)
645 # Retrieve latest modified time of all metafiles
648 for f
in AllWorkSpaceMetaFiles
:
649 if os
.stat(f
)[8] > SrcTimeStamp
:
650 SrcTimeStamp
= os
.stat(f
)[8]
651 self
._SrcTimeStamp
= SrcTimeStamp
653 if GlobalData
.gUseHashCache
:
655 for files
in AllWorkSpaceMetaFiles
:
656 if files
.endswith('.dec'):
662 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'AutoGen.hash'), m
.hexdigest(), True)
663 GlobalData
.gPlatformHash
= m
.hexdigest()
666 # Write metafile list to build directory
668 AutoGenFilePath
= os
.path
.join(self
.BuildDir
, 'AutoGen')
669 if os
.path
.exists (AutoGenFilePath
):
670 os
.remove(AutoGenFilePath
)
671 if not os
.path
.exists(self
.BuildDir
):
672 os
.makedirs(self
.BuildDir
)
673 with
open(os
.path
.join(self
.BuildDir
, 'AutoGen'), 'w+') as file:
674 for f
in AllWorkSpaceMetaFiles
:
678 def _GenPkgLevelHash(self
, Pkg
):
679 PkgDir
= os
.path
.join(self
.BuildDir
, Pkg
.Arch
, Pkg
.PackageName
)
680 CreateDirectory(PkgDir
)
681 HashFile
= os
.path
.join(PkgDir
, Pkg
.PackageName
+ '.hash')
683 # Get .dec file's hash value
684 f
= open(Pkg
.MetaFile
.Path
, 'r')
688 # Get include files hash value
690 for inc
in Pkg
.Includes
:
691 for Root
, Dirs
, Files
in os
.walk(str(inc
)):
693 File_Path
= os
.path
.join(Root
, File
)
694 f
= open(File_Path
, 'r')
698 SaveFileOnChange(HashFile
, m
.hexdigest(), True)
699 if Pkg
.PackageName
not in GlobalData
.gPackageHash
[Pkg
.Arch
]:
700 GlobalData
.gPackageHash
[Pkg
.Arch
][Pkg
.PackageName
] = m
.hexdigest()
702 def _GetMetaFiles(self
, Target
, Toolchain
, Arch
):
703 AllWorkSpaceMetaFiles
= set()
708 AllWorkSpaceMetaFiles
.add (self
.FdfFile
.Path
)
710 FdfFiles
= GlobalData
.gFdfParser
.GetAllIncludedFile()
712 AllWorkSpaceMetaFiles
.add (f
.FileName
)
716 AllWorkSpaceMetaFiles
.add(self
.MetaFile
.Path
)
719 # add build_rule.txt & tools_def.txt
721 AllWorkSpaceMetaFiles
.add(os
.path
.join(GlobalData
.gConfDirectory
, gDefaultBuildRuleFile
))
722 AllWorkSpaceMetaFiles
.add(os
.path
.join(GlobalData
.gConfDirectory
, gDefaultToolsDefFile
))
724 # add BuildOption metafile
726 AllWorkSpaceMetaFiles
.add(os
.path
.join(self
.BuildDir
, 'BuildOptions'))
728 # add PcdToken Number file for Dynamic/DynamicEx Pcd
730 AllWorkSpaceMetaFiles
.add(os
.path
.join(self
.BuildDir
, 'PcdTokenNumber'))
732 for Arch
in self
.ArchList
:
733 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
734 PGen
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
739 for Package
in PGen
.PackageList
:
740 AllWorkSpaceMetaFiles
.add(Package
.MetaFile
.Path
)
745 for filePath
in Platform
._RawData
.IncludedFiles
:
746 AllWorkSpaceMetaFiles
.add(filePath
.Path
)
748 return AllWorkSpaceMetaFiles
750 ## _CheckDuplicateInFV() method
752 # Check whether there is duplicate modules/files exist in FV section.
753 # The check base on the file GUID;
755 def _CheckDuplicateInFV(self
, Fdf
):
756 for Fv
in Fdf
.Profile
.FvDict
:
758 for FfsFile
in Fdf
.Profile
.FvDict
[Fv
].FfsList
:
759 if FfsFile
.InfFileName
and FfsFile
.NameGuid
is None:
764 for Pa
in self
.AutoGenObjectList
:
767 for Module
in Pa
.ModuleAutoGenList
:
768 if path
.normpath(Module
.MetaFile
.File
) == path
.normpath(FfsFile
.InfFileName
):
770 if not Module
.Guid
.upper() in _GuidDict
.keys():
771 _GuidDict
[Module
.Guid
.upper()] = FfsFile
774 EdkLogger
.error("build",
776 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile
.CurrentLineNum
,
777 FfsFile
.CurrentLineContent
,
778 _GuidDict
[Module
.Guid
.upper()].CurrentLineNum
,
779 _GuidDict
[Module
.Guid
.upper()].CurrentLineContent
,
780 Module
.Guid
.upper()),
781 ExtraData
=self
.FdfFile
)
783 # Some INF files not have entity in DSC file.
786 if FfsFile
.InfFileName
.find('$') == -1:
787 InfPath
= NormPath(FfsFile
.InfFileName
)
788 if not os
.path
.exists(InfPath
):
789 EdkLogger
.error('build', GENFDS_ERROR
, "Non-existant Module %s !" % (FfsFile
.InfFileName
))
791 PathClassObj
= PathClass(FfsFile
.InfFileName
, self
.WorkspaceDir
)
793 # Here we just need to get FILE_GUID from INF file, use 'COMMON' as ARCH attribute. and use
794 # BuildObject from one of AutoGenObjectList is enough.
796 InfObj
= self
.AutoGenObjectList
[0].BuildDatabase
.WorkspaceDb
.BuildObject
[PathClassObj
, 'COMMON', self
.BuildTarget
, self
.ToolChain
]
797 if not InfObj
.Guid
.upper() in _GuidDict
.keys():
798 _GuidDict
[InfObj
.Guid
.upper()] = FfsFile
800 EdkLogger
.error("build",
802 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile
.CurrentLineNum
,
803 FfsFile
.CurrentLineContent
,
804 _GuidDict
[InfObj
.Guid
.upper()].CurrentLineNum
,
805 _GuidDict
[InfObj
.Guid
.upper()].CurrentLineContent
,
806 InfObj
.Guid
.upper()),
807 ExtraData
=self
.FdfFile
)
810 if FfsFile
.NameGuid
is not None:
812 # If the NameGuid reference a PCD name.
813 # The style must match: PCD(xxxx.yyy)
815 if gPCDAsGuidPattern
.match(FfsFile
.NameGuid
):
817 # Replace the PCD value.
819 _PcdName
= FfsFile
.NameGuid
.lstrip("PCD(").rstrip(")")
821 for Pa
in self
.AutoGenObjectList
:
823 for PcdItem
in Pa
.AllPcdList
:
824 if (PcdItem
.TokenSpaceGuidCName
+ "." + PcdItem
.TokenCName
) == _PcdName
:
826 # First convert from CFormatGuid to GUID string
828 _PcdGuidString
= GuidStructureStringToGuidString(PcdItem
.DefaultValue
)
830 if not _PcdGuidString
:
832 # Then try Byte array.
834 _PcdGuidString
= GuidStructureByteArrayToGuidString(PcdItem
.DefaultValue
)
836 if not _PcdGuidString
:
838 # Not Byte array or CFormat GUID, raise error.
840 EdkLogger
.error("build",
842 "The format of PCD value is incorrect. PCD: %s , Value: %s\n" % (_PcdName
, PcdItem
.DefaultValue
),
843 ExtraData
=self
.FdfFile
)
845 if not _PcdGuidString
.upper() in _GuidDict
.keys():
846 _GuidDict
[_PcdGuidString
.upper()] = FfsFile
850 EdkLogger
.error("build",
852 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile
.CurrentLineNum
,
853 FfsFile
.CurrentLineContent
,
854 _GuidDict
[_PcdGuidString
.upper()].CurrentLineNum
,
855 _GuidDict
[_PcdGuidString
.upper()].CurrentLineContent
,
856 FfsFile
.NameGuid
.upper()),
857 ExtraData
=self
.FdfFile
)
859 if not FfsFile
.NameGuid
.upper() in _GuidDict
.keys():
860 _GuidDict
[FfsFile
.NameGuid
.upper()] = FfsFile
863 # Two raw file GUID conflict.
865 EdkLogger
.error("build",
867 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile
.CurrentLineNum
,
868 FfsFile
.CurrentLineContent
,
869 _GuidDict
[FfsFile
.NameGuid
.upper()].CurrentLineNum
,
870 _GuidDict
[FfsFile
.NameGuid
.upper()].CurrentLineContent
,
871 FfsFile
.NameGuid
.upper()),
872 ExtraData
=self
.FdfFile
)
875 def _CheckPcdDefineAndType(self
):
877 "FixedAtBuild", "PatchableInModule", "FeatureFlag",
878 "Dynamic", #"DynamicHii", "DynamicVpd",
879 "DynamicEx", # "DynamicExHii", "DynamicExVpd"
882 # This dict store PCDs which are not used by any modules with specified arches
883 UnusedPcd
= OrderedDict()
884 for Pa
in self
.AutoGenObjectList
:
885 # Key of DSC's Pcds dictionary is PcdCName, TokenSpaceGuid
886 for Pcd
in Pa
.Platform
.Pcds
:
887 PcdType
= Pa
.Platform
.Pcds
[Pcd
].Type
889 # If no PCD type, this PCD comes from FDF
893 # Try to remove Hii and Vpd suffix
894 if PcdType
.startswith("DynamicEx"):
895 PcdType
= "DynamicEx"
896 elif PcdType
.startswith("Dynamic"):
899 for Package
in Pa
.PackageList
:
900 # Key of DEC's Pcds dictionary is PcdCName, TokenSpaceGuid, PcdType
901 if (Pcd
[0], Pcd
[1], PcdType
) in Package
.Pcds
:
903 for Type
in PcdTypeList
:
904 if (Pcd
[0], Pcd
[1], Type
) in Package
.Pcds
:
908 "Type [%s] of PCD [%s.%s] in DSC file doesn't match the type [%s] defined in DEC file." \
909 % (Pa
.Platform
.Pcds
[Pcd
].Type
, Pcd
[1], Pcd
[0], Type
),
914 UnusedPcd
.setdefault(Pcd
, []).append(Pa
.Arch
)
916 for Pcd
in UnusedPcd
:
919 "The PCD was not specified by any INF module in the platform for the given architecture.\n"
920 "\tPCD: [%s.%s]\n\tPlatform: [%s]\n\tArch: %s"
921 % (Pcd
[1], Pcd
[0], os
.path
.basename(str(self
.MetaFile
)), str(UnusedPcd
[Pcd
])),
926 return "%s [%s]" % (self
.MetaFile
, ", ".join(self
.ArchList
))
928 ## Return the directory to store FV files
930 if self
._FvDir
is None:
931 self
._FvDir
= path
.join(self
.BuildDir
, 'FV')
934 ## Return the directory to store all intermediate and final files built
935 def _GetBuildDir(self
):
936 if self
._BuildDir
is None:
937 return self
.AutoGenObjectList
[0].BuildDir
939 ## Return the build output directory platform specifies
940 def _GetOutputDir(self
):
941 return self
.Platform
.OutputDirectory
943 ## Return platform name
945 return self
.Platform
.PlatformName
947 ## Return meta-file GUID
949 return self
.Platform
.Guid
951 ## Return platform version
952 def _GetVersion(self
):
953 return self
.Platform
.Version
955 ## Return paths of tools
956 def _GetToolDefinition(self
):
957 return self
.AutoGenObjectList
[0].ToolDefinition
959 ## Return directory of platform makefile
961 # @retval string Makefile directory
963 def _GetMakeFileDir(self
):
964 if self
._MakeFileDir
is None:
965 self
._MakeFileDir
= self
.BuildDir
966 return self
._MakeFileDir
968 ## Return build command string
970 # @retval string Build command string
972 def _GetBuildCommand(self
):
973 if self
._BuildCommand
is None:
974 # BuildCommand should be all the same. So just get one from platform AutoGen
975 self
._BuildCommand
= self
.AutoGenObjectList
[0].BuildCommand
976 return self
._BuildCommand
978 ## Check the PCDs token value conflict in each DEC file.
980 # Will cause build break and raise error message while two PCDs conflict.
984 def _CheckAllPcdsTokenValueConflict(self
):
985 for Pa
in self
.AutoGenObjectList
:
986 for Package
in Pa
.PackageList
:
987 PcdList
= Package
.Pcds
.values()
988 PcdList
.sort(lambda x
, y
: cmp(int(x
.TokenValue
, 0), int(y
.TokenValue
, 0)))
990 while (Count
< len(PcdList
) - 1) :
991 Item
= PcdList
[Count
]
992 ItemNext
= PcdList
[Count
+ 1]
994 # Make sure in the same token space the TokenValue should be unique
996 if (int(Item
.TokenValue
, 0) == int(ItemNext
.TokenValue
, 0)):
997 SameTokenValuePcdList
= []
998 SameTokenValuePcdList
.append(Item
)
999 SameTokenValuePcdList
.append(ItemNext
)
1000 RemainPcdListLength
= len(PcdList
) - Count
- 2
1001 for ValueSameCount
in range(RemainPcdListLength
):
1002 if int(PcdList
[len(PcdList
) - RemainPcdListLength
+ ValueSameCount
].TokenValue
, 0) == int(Item
.TokenValue
, 0):
1003 SameTokenValuePcdList
.append(PcdList
[len(PcdList
) - RemainPcdListLength
+ ValueSameCount
])
1007 # Sort same token value PCD list with TokenGuid and TokenCName
1009 SameTokenValuePcdList
.sort(lambda x
, y
: cmp("%s.%s" % (x
.TokenSpaceGuidCName
, x
.TokenCName
), "%s.%s" % (y
.TokenSpaceGuidCName
, y
.TokenCName
)))
1010 SameTokenValuePcdListCount
= 0
1011 while (SameTokenValuePcdListCount
< len(SameTokenValuePcdList
) - 1):
1013 TemListItem
= SameTokenValuePcdList
[SameTokenValuePcdListCount
]
1014 TemListItemNext
= SameTokenValuePcdList
[SameTokenValuePcdListCount
+ 1]
1016 if (TemListItem
.TokenSpaceGuidCName
== TemListItemNext
.TokenSpaceGuidCName
) and (TemListItem
.TokenCName
!= TemListItemNext
.TokenCName
):
1017 for PcdItem
in GlobalData
.MixedPcd
:
1018 if (TemListItem
.TokenCName
, TemListItem
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
] or \
1019 (TemListItemNext
.TokenCName
, TemListItemNext
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
1025 "The TokenValue [%s] of PCD [%s.%s] is conflict with: [%s.%s] in %s"\
1026 % (TemListItem
.TokenValue
, TemListItem
.TokenSpaceGuidCName
, TemListItem
.TokenCName
, TemListItemNext
.TokenSpaceGuidCName
, TemListItemNext
.TokenCName
, Package
),
1029 SameTokenValuePcdListCount
+= 1
1030 Count
+= SameTokenValuePcdListCount
1033 PcdList
= Package
.Pcds
.values()
1034 PcdList
.sort(lambda x
, y
: cmp("%s.%s" % (x
.TokenSpaceGuidCName
, x
.TokenCName
), "%s.%s" % (y
.TokenSpaceGuidCName
, y
.TokenCName
)))
1036 while (Count
< len(PcdList
) - 1) :
1037 Item
= PcdList
[Count
]
1038 ItemNext
= PcdList
[Count
+ 1]
1040 # Check PCDs with same TokenSpaceGuidCName.TokenCName have same token value as well.
1042 if (Item
.TokenSpaceGuidCName
== ItemNext
.TokenSpaceGuidCName
) and (Item
.TokenCName
== ItemNext
.TokenCName
) and (int(Item
.TokenValue
, 0) != int(ItemNext
.TokenValue
, 0)):
1046 "The TokenValue [%s] of PCD [%s.%s] in %s defined in two places should be same as well."\
1047 % (Item
.TokenValue
, Item
.TokenSpaceGuidCName
, Item
.TokenCName
, Package
),
1051 ## Generate fds command
1052 def _GenFdsCommand(self
):
1053 return (GenMake
.TopLevelMakefile(self
)._TEMPLATE
_.Replace(GenMake
.TopLevelMakefile(self
)._TemplateDict
)).strip()
1055 ## Create makefile for the platform and modules in it
1057 # @param CreateDepsMakeFile Flag indicating if the makefile for
1058 # modules will be created as well
1060 def CreateMakeFile(self
, CreateDepsMakeFile
=False):
1061 if CreateDepsMakeFile
:
1062 for Pa
in self
.AutoGenObjectList
:
1063 Pa
.CreateMakeFile(CreateDepsMakeFile
)
1065 ## Create autogen code for platform and modules
1067 # Since there's no autogen code for platform, this method will do nothing
1068 # if CreateModuleCodeFile is set to False.
1070 # @param CreateDepsCodeFile Flag indicating if creating module's
1071 # autogen code file or not
1073 def CreateCodeFile(self
, CreateDepsCodeFile
=False):
1074 if not CreateDepsCodeFile
:
1076 for Pa
in self
.AutoGenObjectList
:
1077 Pa
.CreateCodeFile(CreateDepsCodeFile
)
1079 ## Create AsBuilt INF file the platform
1081 def CreateAsBuiltInf(self
):
1084 Name
= property(_GetName
)
1085 Guid
= property(_GetGuid
)
1086 Version
= property(_GetVersion
)
1087 OutputDir
= property(_GetOutputDir
)
1089 ToolDefinition
= property(_GetToolDefinition
) # toolcode : tool path
1091 BuildDir
= property(_GetBuildDir
)
1092 FvDir
= property(_GetFvDir
)
1093 MakeFileDir
= property(_GetMakeFileDir
)
1094 BuildCommand
= property(_GetBuildCommand
)
1095 GenFdsCommand
= property(_GenFdsCommand
)
1097 ## AutoGen class for platform
1099 # PlatformAutoGen class will process the original information in platform
1100 # file in order to generate makefile for platform.
1102 class PlatformAutoGen(AutoGen
):
1103 # call super().__init__ then call the worker function with different parameter count
1104 def __init__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
1108 super(PlatformAutoGen
, self
).__init
__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
1109 self
._InitWorker
(Workspace
, MetaFile
, Target
, Toolchain
, Arch
)
1112 # Used to store all PCDs for both PEI and DXE phase, in order to generate
1113 # correct PCD database
1116 _NonDynaPcdList_
= []
1120 # The priority list while override build option
1122 PrioList
= {"0x11111" : 16, # TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE (Highest)
1123 "0x01111" : 15, # ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
1124 "0x10111" : 14, # TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE
1125 "0x00111" : 13, # ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE
1126 "0x11011" : 12, # TARGET_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
1127 "0x01011" : 11, # ******_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
1128 "0x10011" : 10, # TARGET_*********_****_COMMANDTYPE_ATTRIBUTE
1129 "0x00011" : 9, # ******_*********_****_COMMANDTYPE_ATTRIBUTE
1130 "0x11101" : 8, # TARGET_TOOLCHAIN_ARCH_***********_ATTRIBUTE
1131 "0x01101" : 7, # ******_TOOLCHAIN_ARCH_***********_ATTRIBUTE
1132 "0x10101" : 6, # TARGET_*********_ARCH_***********_ATTRIBUTE
1133 "0x00101" : 5, # ******_*********_ARCH_***********_ATTRIBUTE
1134 "0x11001" : 4, # TARGET_TOOLCHAIN_****_***********_ATTRIBUTE
1135 "0x01001" : 3, # ******_TOOLCHAIN_****_***********_ATTRIBUTE
1136 "0x10001" : 2, # TARGET_*********_****_***********_ATTRIBUTE
1137 "0x00001" : 1} # ******_*********_****_***********_ATTRIBUTE (Lowest)
1139 ## Initialize PlatformAutoGen
1142 # @param Workspace WorkspaceAutoGen object
1143 # @param PlatformFile Platform file (DSC file)
1144 # @param Target Build target (DEBUG, RELEASE)
1145 # @param Toolchain Name of tool chain
1146 # @param Arch arch of the platform supports
1148 def _InitWorker(self
, Workspace
, PlatformFile
, Target
, Toolchain
, Arch
):
1149 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen platform [%s] [%s]" % (PlatformFile
, Arch
))
1150 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (PlatformFile
, Arch
, Toolchain
, Target
)
1152 self
.MetaFile
= PlatformFile
1153 self
.Workspace
= Workspace
1154 self
.WorkspaceDir
= Workspace
.WorkspaceDir
1155 self
.ToolChain
= Toolchain
1156 self
.BuildTarget
= Target
1158 self
.SourceDir
= PlatformFile
.SubDir
1159 self
.SourceOverrideDir
= None
1160 self
.FdTargetList
= self
.Workspace
.FdTargetList
1161 self
.FvTargetList
= self
.Workspace
.FvTargetList
1162 self
.AllPcdList
= []
1163 # get the original module/package/platform objects
1164 self
.BuildDatabase
= Workspace
.BuildDatabase
1165 self
.DscBuildDataObj
= Workspace
.Platform
1166 self
._GuidDict
= Workspace
._GuidDict
1168 # flag indicating if the makefile/C-code file has been created or not
1169 self
.IsMakeFileCreated
= False
1170 self
.IsCodeFileCreated
= False
1172 self
._Platform
= None
1175 self
._Version
= None
1177 self
._BuildRule
= None
1178 self
._SourceDir
= None
1179 self
._BuildDir
= None
1180 self
._OutputDir
= None
1182 self
._MakeFileDir
= None
1183 self
._FdfFile
= None
1185 self
._PcdTokenNumber
= None # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
1186 self
._DynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1187 self
._NonDynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1188 self
._NonDynamicPcdDict
= {}
1190 self
._ToolDefinitions
= None
1191 self
._ToolDefFile
= None # toolcode : tool path
1192 self
._ToolChainFamily
= None
1193 self
._BuildRuleFamily
= None
1194 self
._BuildOption
= None # toolcode : option
1195 self
._EdkBuildOption
= None # edktoolcode : option
1196 self
._EdkIIBuildOption
= None # edkiitoolcode : option
1197 self
._PackageList
= None
1198 self
._ModuleAutoGenList
= None
1199 self
._LibraryAutoGenList
= None
1200 self
._BuildCommand
= None
1201 self
._AsBuildInfList
= []
1202 self
._AsBuildModuleList
= []
1204 self
.VariableInfo
= None
1206 if GlobalData
.gFdfParser
is not None:
1207 self
._AsBuildInfList
= GlobalData
.gFdfParser
.Profile
.InfList
1208 for Inf
in self
._AsBuildInfList
:
1209 InfClass
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, self
.Arch
)
1210 M
= self
.BuildDatabase
[InfClass
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1211 if not M
.IsSupportedArch
:
1213 self
._AsBuildModuleList
.append(InfClass
)
1214 # get library/modules for build
1215 self
.LibraryBuildDirectoryList
= []
1216 self
.ModuleBuildDirectoryList
= []
1221 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
1223 ## Create autogen code for platform and modules
1225 # Since there's no autogen code for platform, this method will do nothing
1226 # if CreateModuleCodeFile is set to False.
1228 # @param CreateModuleCodeFile Flag indicating if creating module's
1229 # autogen code file or not
1231 def CreateCodeFile(self
, CreateModuleCodeFile
=False):
1232 # only module has code to be greated, so do nothing if CreateModuleCodeFile is False
1233 if self
.IsCodeFileCreated
or not CreateModuleCodeFile
:
1236 for Ma
in self
.ModuleAutoGenList
:
1237 Ma
.CreateCodeFile(True)
1239 # don't do this twice
1240 self
.IsCodeFileCreated
= True
1242 ## Generate Fds Command
1243 def _GenFdsCommand(self
):
1244 return self
.Workspace
.GenFdsCommand
1246 ## Create makefile for the platform and mdoules in it
1248 # @param CreateModuleMakeFile Flag indicating if the makefile for
1249 # modules will be created as well
1251 def CreateMakeFile(self
, CreateModuleMakeFile
=False, FfsCommand
= {}):
1252 if CreateModuleMakeFile
:
1253 for ModuleFile
in self
.Platform
.Modules
:
1254 Ma
= ModuleAutoGen(self
.Workspace
, ModuleFile
, self
.BuildTarget
,
1255 self
.ToolChain
, self
.Arch
, self
.MetaFile
)
1256 if (ModuleFile
.File
, self
.Arch
) in FfsCommand
:
1257 Ma
.CreateMakeFile(True, FfsCommand
[ModuleFile
.File
, self
.Arch
])
1259 Ma
.CreateMakeFile(True)
1260 #Ma.CreateAsBuiltInf()
1262 # no need to create makefile for the platform more than once
1263 if self
.IsMakeFileCreated
:
1266 # create library/module build dirs for platform
1267 Makefile
= GenMake
.PlatformMakefile(self
)
1268 self
.LibraryBuildDirectoryList
= Makefile
.GetLibraryBuildDirectoryList()
1269 self
.ModuleBuildDirectoryList
= Makefile
.GetModuleBuildDirectoryList()
1271 self
.IsMakeFileCreated
= True
1273 ## Deal with Shared FixedAtBuild Pcds
1275 def CollectFixedAtBuildPcds(self
):
1276 for LibAuto
in self
.LibraryAutoGenList
:
1277 FixedAtBuildPcds
= {}
1278 ShareFixedAtBuildPcdsSameValue
= {}
1279 for Module
in LibAuto
._ReferenceModules
:
1280 for Pcd
in Module
.FixedAtBuildPcds
+ LibAuto
.FixedAtBuildPcds
:
1281 key
= ".".join((Pcd
.TokenSpaceGuidCName
,Pcd
.TokenCName
))
1282 if key
not in FixedAtBuildPcds
:
1283 ShareFixedAtBuildPcdsSameValue
[key
] = True
1284 FixedAtBuildPcds
[key
] = Pcd
.DefaultValue
1286 if FixedAtBuildPcds
[key
] != Pcd
.DefaultValue
:
1287 ShareFixedAtBuildPcdsSameValue
[key
] = False
1288 for Pcd
in LibAuto
.FixedAtBuildPcds
:
1289 key
= ".".join((Pcd
.TokenSpaceGuidCName
,Pcd
.TokenCName
))
1290 if (Pcd
.TokenCName
,Pcd
.TokenSpaceGuidCName
) not in self
.NonDynamicPcdDict
:
1293 DscPcd
= self
.NonDynamicPcdDict
[(Pcd
.TokenCName
,Pcd
.TokenSpaceGuidCName
)]
1294 if DscPcd
.Type
!= "FixedAtBuild":
1296 if key
in ShareFixedAtBuildPcdsSameValue
and ShareFixedAtBuildPcdsSameValue
[key
]:
1297 LibAuto
.ConstPcd
[key
] = Pcd
.DefaultValue
1299 def CollectVariables(self
, DynamicPcdSet
):
1303 if self
.Workspace
.FdfFile
:
1304 FdDict
= self
.Workspace
.FdfProfile
.FdDict
[GlobalData
.gFdfParser
.CurrentFdName
]
1305 for FdRegion
in FdDict
.RegionList
:
1306 for item
in FdRegion
.RegionDataList
:
1307 if self
.Platform
.VpdToolGuid
.strip() and self
.Platform
.VpdToolGuid
in item
:
1308 VpdRegionSize
= FdRegion
.Size
1309 VpdRegionBase
= FdRegion
.Offset
1313 VariableInfo
= VariableMgr(self
.DscBuildDataObj
._GetDefaultStores
(),self
.DscBuildDataObj
._GetSkuIds
())
1314 VariableInfo
.SetVpdRegionMaxSize(VpdRegionSize
)
1315 VariableInfo
.SetVpdRegionOffset(VpdRegionBase
)
1317 for Pcd
in DynamicPcdSet
:
1318 pcdname
= ".".join((Pcd
.TokenSpaceGuidCName
,Pcd
.TokenCName
))
1319 for SkuName
in Pcd
.SkuInfoList
:
1320 Sku
= Pcd
.SkuInfoList
[SkuName
]
1322 if SkuId
is None or SkuId
== '':
1324 if len(Sku
.VariableName
) > 0:
1325 VariableGuidStructure
= Sku
.VariableGuidValue
1326 VariableGuid
= GuidStructureStringToGuidString(VariableGuidStructure
)
1327 for StorageName
in Sku
.DefaultStoreDict
:
1328 VariableInfo
.append_variable(var_info(Index
,pcdname
,StorageName
,SkuName
, StringToArray(Sku
.VariableName
),VariableGuid
, Sku
.VariableOffset
, Sku
.VariableAttribute
, Sku
.HiiDefaultValue
,Sku
.DefaultStoreDict
[StorageName
],Pcd
.DatumType
))
1332 def UpdateNVStoreMaxSize(self
,OrgVpdFile
):
1333 if self
.VariableInfo
:
1334 VpdMapFilePath
= os
.path
.join(self
.BuildDir
, "FV", "%s.map" % self
.Platform
.VpdToolGuid
)
1335 PcdNvStoreDfBuffer
= [item
for item
in self
._DynamicPcdList
if item
.TokenCName
== "PcdNvStoreDefaultValueBuffer" and item
.TokenSpaceGuidCName
== "gEfiMdeModulePkgTokenSpaceGuid"]
1337 if PcdNvStoreDfBuffer
:
1338 if os
.path
.exists(VpdMapFilePath
):
1339 OrgVpdFile
.Read(VpdMapFilePath
)
1340 PcdItems
= OrgVpdFile
.GetOffset(PcdNvStoreDfBuffer
[0])
1341 NvStoreOffset
= PcdItems
.values()[0].strip() if PcdItems
else '0'
1343 EdkLogger
.error("build", FILE_READ_FAILURE
, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath
)
1345 NvStoreOffset
= int(NvStoreOffset
,16) if NvStoreOffset
.upper().startswith("0X") else int(NvStoreOffset
)
1346 default_skuobj
= PcdNvStoreDfBuffer
[0].SkuInfoList
.get("DEFAULT")
1347 maxsize
= self
.VariableInfo
.VpdRegionSize
- NvStoreOffset
if self
.VariableInfo
.VpdRegionSize
else len(default_skuobj
.DefaultValue
.split(","))
1348 var_data
= self
.VariableInfo
.PatchNVStoreDefaultMaxSize(maxsize
)
1350 if var_data
and default_skuobj
:
1351 default_skuobj
.DefaultValue
= var_data
1352 PcdNvStoreDfBuffer
[0].DefaultValue
= var_data
1353 PcdNvStoreDfBuffer
[0].SkuInfoList
.clear()
1354 PcdNvStoreDfBuffer
[0].SkuInfoList
['DEFAULT'] = default_skuobj
1355 PcdNvStoreDfBuffer
[0].MaxDatumSize
= str(len(default_skuobj
.DefaultValue
.split(",")))
1359 ## Collect dynamic PCDs
1361 # Gather dynamic PCDs list from each module and their settings from platform
1362 # This interface should be invoked explicitly when platform action is created.
1364 def CollectPlatformDynamicPcds(self
):
1366 for key
in self
.Platform
.Pcds
:
1367 for SinglePcd
in GlobalData
.MixedPcd
:
1368 if (self
.Platform
.Pcds
[key
].TokenCName
, self
.Platform
.Pcds
[key
].TokenSpaceGuidCName
) == SinglePcd
:
1369 for item
in GlobalData
.MixedPcd
[SinglePcd
]:
1370 Pcd_Type
= item
[0].split('_')[-1]
1371 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 \
1372 (Pcd_Type
== TAB_PCDS_DYNAMIC
and self
.Platform
.Pcds
[key
].Type
in GenC
.gDynamicPcd
):
1373 Value
= self
.Platform
.Pcds
[key
]
1374 Value
.TokenCName
= self
.Platform
.Pcds
[key
].TokenCName
+ '_' + Pcd_Type
1376 newkey
= (Value
.TokenCName
, key
[1])
1378 newkey
= (Value
.TokenCName
, key
[1], key
[2])
1379 del self
.Platform
.Pcds
[key
]
1380 self
.Platform
.Pcds
[newkey
] = Value
1388 # for gathering error information
1389 NoDatumTypePcdList
= set()
1391 self
._GuidValue
= {}
1393 for InfName
in self
._AsBuildInfList
:
1394 InfName
= mws
.join(self
.WorkspaceDir
, InfName
)
1395 FdfModuleList
.append(os
.path
.normpath(InfName
))
1396 for F
in self
.Platform
.Modules
.keys():
1397 M
= ModuleAutoGen(self
.Workspace
, F
, self
.BuildTarget
, self
.ToolChain
, self
.Arch
, self
.MetaFile
)
1398 #GuidValue.update(M.Guids)
1400 self
.Platform
.Modules
[F
].M
= M
1402 for PcdFromModule
in M
.ModulePcdList
+ M
.LibraryPcdList
:
1403 # make sure that the "VOID*" kind of datum has MaxDatumSize set
1404 if PcdFromModule
.DatumType
== "VOID*" and PcdFromModule
.MaxDatumSize
in [None, '']:
1405 NoDatumTypePcdList
.add("%s.%s [%s]" % (PcdFromModule
.TokenSpaceGuidCName
, PcdFromModule
.TokenCName
, F
))
1407 # Check the PCD from Binary INF or Source INF
1408 if M
.IsBinaryModule
== True:
1409 PcdFromModule
.IsFromBinaryInf
= True
1411 # Check the PCD from DSC or not
1412 if (PcdFromModule
.TokenCName
, PcdFromModule
.TokenSpaceGuidCName
) in self
.Platform
.Pcds
.keys():
1413 PcdFromModule
.IsFromDsc
= True
1415 PcdFromModule
.IsFromDsc
= False
1416 if PcdFromModule
.Type
in GenC
.gDynamicPcd
or PcdFromModule
.Type
in GenC
.gDynamicExPcd
:
1417 if F
.Path
not in FdfModuleList
:
1418 # If one of the Source built modules listed in the DSC is not listed
1419 # in FDF modules, and the INF lists a PCD can only use the PcdsDynamic
1420 # access method (it is only listed in the DEC file that declares the
1421 # PCD as PcdsDynamic), then build tool will report warning message
1422 # notify the PI that they are attempting to build a module that must
1423 # be included in a flash image in order to be functional. These Dynamic
1424 # PCD will not be added into the Database unless it is used by other
1425 # modules that are included in the FDF file.
1426 if PcdFromModule
.Type
in GenC
.gDynamicPcd
and \
1427 PcdFromModule
.IsFromBinaryInf
== False:
1428 # Print warning message to let the developer make a determine.
1429 if PcdFromModule
not in PcdNotInDb
:
1430 PcdNotInDb
.append(PcdFromModule
)
1432 # If one of the Source built modules listed in the DSC is not listed in
1433 # FDF modules, and the INF lists a PCD can only use the PcdsDynamicEx
1434 # access method (it is only listed in the DEC file that declares the
1435 # PCD as PcdsDynamicEx), then DO NOT break the build; DO NOT add the
1436 # PCD to the Platform's PCD Database.
1437 if PcdFromModule
.Type
in GenC
.gDynamicExPcd
:
1438 if PcdFromModule
not in PcdNotInDb
:
1439 PcdNotInDb
.append(PcdFromModule
)
1442 # If a dynamic PCD used by a PEM module/PEI module & DXE module,
1443 # it should be stored in Pcd PEI database, If a dynamic only
1444 # used by DXE module, it should be stored in DXE PCD database.
1445 # The default Phase is DXE
1447 if M
.ModuleType
in ["PEIM", "PEI_CORE"]:
1448 PcdFromModule
.Phase
= "PEI"
1449 if PcdFromModule
not in self
._DynaPcdList
_:
1450 self
._DynaPcdList
_.append(PcdFromModule
)
1451 elif PcdFromModule
.Phase
== 'PEI':
1452 # overwrite any the same PCD existing, if Phase is PEI
1453 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1454 self
._DynaPcdList
_[Index
] = PcdFromModule
1455 elif PcdFromModule
not in self
._NonDynaPcdList
_:
1456 self
._NonDynaPcdList
_.append(PcdFromModule
)
1457 elif PcdFromModule
in self
._NonDynaPcdList
_ and PcdFromModule
.IsFromBinaryInf
== True:
1458 Index
= self
._NonDynaPcdList
_.index(PcdFromModule
)
1459 if self
._NonDynaPcdList
_[Index
].IsFromBinaryInf
== False:
1460 #The PCD from Binary INF will override the same one from source INF
1461 self
._NonDynaPcdList
_.remove (self
._NonDynaPcdList
_[Index
])
1462 PcdFromModule
.Pending
= False
1463 self
._NonDynaPcdList
_.append (PcdFromModule
)
1464 # Parse the DynamicEx PCD from the AsBuild INF module list of FDF.
1466 for ModuleInf
in self
.Platform
.Modules
.keys():
1467 DscModuleList
.append (os
.path
.normpath(ModuleInf
.Path
))
1468 # add the PCD from modules that listed in FDF but not in DSC to Database
1469 for InfName
in FdfModuleList
:
1470 if InfName
not in DscModuleList
:
1471 InfClass
= PathClass(InfName
)
1472 M
= self
.BuildDatabase
[InfClass
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1473 # If a module INF in FDF but not in current arch's DSC module list, it must be module (either binary or source)
1474 # for different Arch. PCDs in source module for different Arch is already added before, so skip the source module here.
1475 # For binary module, if in current arch, we need to list the PCDs into database.
1476 if not M
.IsSupportedArch
:
1478 # Override the module PCD setting by platform setting
1479 ModulePcdList
= self
.ApplyPcdSetting(M
, M
.Pcds
)
1480 for PcdFromModule
in ModulePcdList
:
1481 PcdFromModule
.IsFromBinaryInf
= True
1482 PcdFromModule
.IsFromDsc
= False
1483 # Only allow the DynamicEx and Patchable PCD in AsBuild INF
1484 if PcdFromModule
.Type
not in GenC
.gDynamicExPcd
and PcdFromModule
.Type
not in TAB_PCDS_PATCHABLE_IN_MODULE
:
1485 EdkLogger
.error("build", AUTOGEN_ERROR
, "PCD setting error",
1487 ExtraData
="\n\tExisted %s PCD %s in:\n\t\t%s\n"
1488 % (PcdFromModule
.Type
, PcdFromModule
.TokenCName
, InfName
))
1489 # make sure that the "VOID*" kind of datum has MaxDatumSize set
1490 if PcdFromModule
.DatumType
== "VOID*" and PcdFromModule
.MaxDatumSize
in [None, '']:
1491 NoDatumTypePcdList
.add("%s.%s [%s]" % (PcdFromModule
.TokenSpaceGuidCName
, PcdFromModule
.TokenCName
, InfName
))
1492 if M
.ModuleType
in ["PEIM", "PEI_CORE"]:
1493 PcdFromModule
.Phase
= "PEI"
1494 if PcdFromModule
not in self
._DynaPcdList
_ and PcdFromModule
.Type
in GenC
.gDynamicExPcd
:
1495 self
._DynaPcdList
_.append(PcdFromModule
)
1496 elif PcdFromModule
not in self
._NonDynaPcdList
_ and PcdFromModule
.Type
in TAB_PCDS_PATCHABLE_IN_MODULE
:
1497 self
._NonDynaPcdList
_.append(PcdFromModule
)
1498 if PcdFromModule
in self
._DynaPcdList
_ and PcdFromModule
.Phase
== 'PEI' and PcdFromModule
.Type
in GenC
.gDynamicExPcd
:
1499 # Overwrite the phase of any the same PCD existing, if Phase is PEI.
1500 # It is to solve the case that a dynamic PCD used by a PEM module/PEI
1501 # module & DXE module at a same time.
1502 # Overwrite the type of the PCDs in source INF by the type of AsBuild
1503 # INF file as DynamicEx.
1504 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1505 self
._DynaPcdList
_[Index
].Phase
= PcdFromModule
.Phase
1506 self
._DynaPcdList
_[Index
].Type
= PcdFromModule
.Type
1507 for PcdFromModule
in self
._NonDynaPcdList
_:
1508 # If a PCD is not listed in the DSC file, but binary INF files used by
1509 # this platform all (that use this PCD) list the PCD in a [PatchPcds]
1510 # section, AND all source INF files used by this platform the build
1511 # that use the PCD list the PCD in either a [Pcds] or [PatchPcds]
1512 # section, then the tools must NOT add the PCD to the Platform's PCD
1513 # Database; the build must assign the access method for this PCD as
1514 # PcdsPatchableInModule.
1515 if PcdFromModule
not in self
._DynaPcdList
_:
1517 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1518 if PcdFromModule
.IsFromDsc
== False and \
1519 PcdFromModule
.Type
in TAB_PCDS_PATCHABLE_IN_MODULE
and \
1520 PcdFromModule
.IsFromBinaryInf
== True and \
1521 self
._DynaPcdList
_[Index
].IsFromBinaryInf
== False:
1522 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1523 self
._DynaPcdList
_.remove (self
._DynaPcdList
_[Index
])
1525 # print out error information and break the build, if error found
1526 if len(NoDatumTypePcdList
) > 0:
1527 NoDatumTypePcdListString
= "\n\t\t".join(NoDatumTypePcdList
)
1528 EdkLogger
.error("build", AUTOGEN_ERROR
, "PCD setting error",
1530 ExtraData
="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"
1531 % NoDatumTypePcdListString
)
1532 self
._NonDynamicPcdList
= self
._NonDynaPcdList
_
1533 self
._DynamicPcdList
= self
._DynaPcdList
_
1535 # Sort dynamic PCD list to:
1536 # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should
1537 # try to be put header of dynamicd List
1538 # 2) If PCD is HII type, the PCD item should be put after unicode type PCD
1540 # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.
1542 UnicodePcdArray
= set()
1544 OtherPcdArray
= set()
1546 VpdFile
= VpdInfoFile
.VpdInfoFile()
1547 NeedProcessVpdMapFile
= False
1549 for pcd
in self
.Platform
.Pcds
.keys():
1550 if pcd
not in self
._PlatformPcds
.keys():
1551 self
._PlatformPcds
[pcd
] = self
.Platform
.Pcds
[pcd
]
1553 for item
in self
._PlatformPcds
:
1554 if self
._PlatformPcds
[item
].DatumType
and self
._PlatformPcds
[item
].DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
1555 self
._PlatformPcds
[item
].DatumType
= "VOID*"
1557 if (self
.Workspace
.ArchList
[-1] == self
.Arch
):
1558 for Pcd
in self
._DynamicPcdList
:
1559 # just pick the a value to determine whether is unicode string type
1560 Sku
= Pcd
.SkuInfoList
[Pcd
.SkuInfoList
.keys()[0]]
1561 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1563 if Pcd
.DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
1564 Pcd
.DatumType
= "VOID*"
1566 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
1567 # if found HII type PCD then insert to right of UnicodeIndex
1568 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
1569 VpdPcdDict
[(Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
)] = Pcd
1571 #Collect DynamicHii PCD values and assign it to DynamicExVpd PCD gEfiMdeModulePkgTokenSpaceGuid.PcdNvStoreDefaultValueBuffer
1572 PcdNvStoreDfBuffer
= VpdPcdDict
.get(("PcdNvStoreDefaultValueBuffer","gEfiMdeModulePkgTokenSpaceGuid"))
1573 if PcdNvStoreDfBuffer
:
1574 self
.VariableInfo
= self
.CollectVariables(self
._DynamicPcdList
)
1575 vardump
= self
.VariableInfo
.dump()
1577 PcdNvStoreDfBuffer
.DefaultValue
= vardump
1578 for skuname
in PcdNvStoreDfBuffer
.SkuInfoList
:
1579 PcdNvStoreDfBuffer
.SkuInfoList
[skuname
].DefaultValue
= vardump
1580 PcdNvStoreDfBuffer
.MaxDatumSize
= str(len(vardump
.split(",")))
1582 PlatformPcds
= self
._PlatformPcds
.keys()
1585 # Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.
1588 for PcdKey
in PlatformPcds
:
1589 Pcd
= self
._PlatformPcds
[PcdKey
]
1590 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
] and \
1591 PcdKey
in VpdPcdDict
:
1592 Pcd
= VpdPcdDict
[PcdKey
]
1594 DefaultSku
= Pcd
.SkuInfoList
.get('DEFAULT')
1596 PcdValue
= DefaultSku
.DefaultValue
1597 if PcdValue
not in SkuValueMap
:
1598 SkuValueMap
[PcdValue
] = []
1599 VpdFile
.Add(Pcd
, 'DEFAULT',DefaultSku
.VpdOffset
)
1600 SkuValueMap
[PcdValue
].append(DefaultSku
)
1602 for (SkuName
,Sku
) in Pcd
.SkuInfoList
.items():
1603 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1604 PcdValue
= Sku
.DefaultValue
1606 PcdValue
= Pcd
.DefaultValue
1607 if Sku
.VpdOffset
!= '*':
1608 if PcdValue
.startswith("{"):
1610 elif PcdValue
.startswith("L"):
1615 VpdOffset
= int(Sku
.VpdOffset
)
1618 VpdOffset
= int(Sku
.VpdOffset
, 16)
1620 EdkLogger
.error("build", FORMAT_INVALID
, "Invalid offset value %s for PCD %s.%s." % (Sku
.VpdOffset
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
1621 if VpdOffset
% Alignment
!= 0:
1622 if PcdValue
.startswith("{"):
1623 EdkLogger
.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
), File
=self
.MetaFile
)
1625 EdkLogger
.error("build", FORMAT_INVALID
, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
, Alignment
))
1626 if PcdValue
not in SkuValueMap
:
1627 SkuValueMap
[PcdValue
] = []
1628 VpdFile
.Add(Pcd
, SkuName
,Sku
.VpdOffset
)
1629 SkuValueMap
[PcdValue
].append(Sku
)
1630 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
1631 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== "*":
1632 NeedProcessVpdMapFile
= True
1633 if self
.Platform
.VpdToolGuid
is None or self
.Platform
.VpdToolGuid
== '':
1634 EdkLogger
.error("Build", FILE_NOT_FOUND
, \
1635 "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.")
1637 VpdSkuMap
[PcdKey
] = SkuValueMap
1639 # Fix the PCDs define in VPD PCD section that never referenced by module.
1640 # An example is PCD for signature usage.
1642 for DscPcd
in PlatformPcds
:
1643 DscPcdEntry
= self
._PlatformPcds
[DscPcd
]
1644 if DscPcdEntry
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
1645 if not (self
.Platform
.VpdToolGuid
is None or self
.Platform
.VpdToolGuid
== ''):
1647 for VpdPcd
in VpdFile
._VpdArray
.keys():
1648 # This PCD has been referenced by module
1649 if (VpdPcd
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
1650 (VpdPcd
.TokenCName
== DscPcdEntry
.TokenCName
):
1653 # Not found, it should be signature
1655 # just pick the a value to determine whether is unicode string type
1657 SkuObjList
= DscPcdEntry
.SkuInfoList
.items()
1658 DefaultSku
= DscPcdEntry
.SkuInfoList
.get('DEFAULT')
1660 defaultindex
= SkuObjList
.index(('DEFAULT',DefaultSku
))
1661 SkuObjList
[0],SkuObjList
[defaultindex
] = SkuObjList
[defaultindex
],SkuObjList
[0]
1662 for (SkuName
,Sku
) in SkuObjList
:
1663 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1665 # Need to iterate DEC pcd information to get the value & datumtype
1666 for eachDec
in self
.PackageList
:
1667 for DecPcd
in eachDec
.Pcds
:
1668 DecPcdEntry
= eachDec
.Pcds
[DecPcd
]
1669 if (DecPcdEntry
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
1670 (DecPcdEntry
.TokenCName
== DscPcdEntry
.TokenCName
):
1671 # Print warning message to let the developer make a determine.
1672 EdkLogger
.warn("build", "Unreferenced vpd pcd used!",
1673 File
=self
.MetaFile
, \
1674 ExtraData
= "PCD: %s.%s used in the DSC file %s is unreferenced." \
1675 %(DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
, self
.Platform
.MetaFile
.Path
))
1677 DscPcdEntry
.DatumType
= DecPcdEntry
.DatumType
1678 DscPcdEntry
.DefaultValue
= DecPcdEntry
.DefaultValue
1679 DscPcdEntry
.TokenValue
= DecPcdEntry
.TokenValue
1680 DscPcdEntry
.TokenSpaceGuidValue
= eachDec
.Guids
[DecPcdEntry
.TokenSpaceGuidCName
]
1681 # Only fix the value while no value provided in DSC file.
1682 if (Sku
.DefaultValue
== "" or Sku
.DefaultValue
==None):
1683 DscPcdEntry
.SkuInfoList
[DscPcdEntry
.SkuInfoList
.keys()[0]].DefaultValue
= DecPcdEntry
.DefaultValue
1685 if DscPcdEntry
not in self
._DynamicPcdList
:
1686 self
._DynamicPcdList
.append(DscPcdEntry
)
1687 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1688 PcdValue
= Sku
.DefaultValue
1690 PcdValue
= DscPcdEntry
.DefaultValue
1691 if Sku
.VpdOffset
!= '*':
1692 if PcdValue
.startswith("{"):
1694 elif PcdValue
.startswith("L"):
1699 VpdOffset
= int(Sku
.VpdOffset
)
1702 VpdOffset
= int(Sku
.VpdOffset
, 16)
1704 EdkLogger
.error("build", FORMAT_INVALID
, "Invalid offset value %s for PCD %s.%s." % (Sku
.VpdOffset
, DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
))
1705 if VpdOffset
% Alignment
!= 0:
1706 if PcdValue
.startswith("{"):
1707 EdkLogger
.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
), File
=self
.MetaFile
)
1709 EdkLogger
.error("build", FORMAT_INVALID
, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
, Alignment
))
1710 if PcdValue
not in SkuValueMap
:
1711 SkuValueMap
[PcdValue
] = []
1712 VpdFile
.Add(DscPcdEntry
, SkuName
,Sku
.VpdOffset
)
1713 SkuValueMap
[PcdValue
].append(Sku
)
1714 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== "*":
1715 NeedProcessVpdMapFile
= True
1716 if DscPcdEntry
.DatumType
== 'VOID*' and PcdValue
.startswith("L"):
1717 UnicodePcdArray
.add(DscPcdEntry
)
1718 elif len(Sku
.VariableName
) > 0:
1719 HiiPcdArray
.add(DscPcdEntry
)
1721 OtherPcdArray
.add(DscPcdEntry
)
1723 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
1724 VpdSkuMap
[DscPcd
] = SkuValueMap
1725 if (self
.Platform
.FlashDefinition
is None or self
.Platform
.FlashDefinition
== '') and \
1726 VpdFile
.GetCount() != 0:
1727 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
,
1728 "Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD." % str(self
.Platform
.MetaFile
))
1730 if VpdFile
.GetCount() != 0:
1732 self
.FixVpdOffset(VpdFile
)
1734 self
.FixVpdOffset(self
.UpdateNVStoreMaxSize(VpdFile
))
1736 # Process VPD map file generated by third party BPDG tool
1737 if NeedProcessVpdMapFile
:
1738 VpdMapFilePath
= os
.path
.join(self
.BuildDir
, "FV", "%s.map" % self
.Platform
.VpdToolGuid
)
1739 if os
.path
.exists(VpdMapFilePath
):
1740 VpdFile
.Read(VpdMapFilePath
)
1743 for pcd
in VpdSkuMap
:
1744 vpdinfo
= VpdFile
.GetVpdInfo(pcd
)
1746 # just pick the a value to determine whether is unicode string type
1748 for pcdvalue
in VpdSkuMap
[pcd
]:
1749 for sku
in VpdSkuMap
[pcd
][pcdvalue
]:
1750 for item
in vpdinfo
:
1751 if item
[2] == pcdvalue
:
1752 sku
.VpdOffset
= item
[1]
1754 EdkLogger
.error("build", FILE_READ_FAILURE
, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath
)
1756 # Delete the DynamicPcdList At the last time enter into this function
1757 for Pcd
in self
._DynamicPcdList
:
1758 # just pick the a value to determine whether is unicode string type
1759 Sku
= Pcd
.SkuInfoList
[Pcd
.SkuInfoList
.keys()[0]]
1760 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1762 if Pcd
.DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
1763 Pcd
.DatumType
= "VOID*"
1765 PcdValue
= Sku
.DefaultValue
1766 if Pcd
.DatumType
== 'VOID*' and PcdValue
.startswith("L"):
1767 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
1768 UnicodePcdArray
.add(Pcd
)
1769 elif len(Sku
.VariableName
) > 0:
1770 # if found HII type PCD then insert to right of UnicodeIndex
1771 HiiPcdArray
.add(Pcd
)
1773 OtherPcdArray
.add(Pcd
)
1774 del self
._DynamicPcdList
[:]
1775 self
._DynamicPcdList
.extend(list(UnicodePcdArray
))
1776 self
._DynamicPcdList
.extend(list(HiiPcdArray
))
1777 self
._DynamicPcdList
.extend(list(OtherPcdArray
))
1778 allskuset
= [(SkuName
,Sku
.SkuId
) for pcd
in self
._DynamicPcdList
for (SkuName
,Sku
) in pcd
.SkuInfoList
.items()]
1779 for pcd
in self
._DynamicPcdList
:
1780 if len(pcd
.SkuInfoList
) == 1:
1781 for (SkuName
,SkuId
) in allskuset
:
1782 if type(SkuId
) in (str,unicode) and eval(SkuId
) == 0 or SkuId
== 0:
1784 pcd
.SkuInfoList
[SkuName
] = copy
.deepcopy(pcd
.SkuInfoList
['DEFAULT'])
1785 pcd
.SkuInfoList
[SkuName
].SkuId
= SkuId
1786 self
.AllPcdList
= self
._NonDynamicPcdList
+ self
._DynamicPcdList
1788 def FixVpdOffset(self
,VpdFile
):
1789 FvPath
= os
.path
.join(self
.BuildDir
, "FV")
1790 if not os
.path
.exists(FvPath
):
1794 EdkLogger
.error("build", FILE_WRITE_FAILURE
, "Fail to create FV folder under %s" % self
.BuildDir
)
1796 VpdFilePath
= os
.path
.join(FvPath
, "%s.txt" % self
.Platform
.VpdToolGuid
)
1798 if VpdFile
.Write(VpdFilePath
):
1799 # retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.
1801 for ToolDef
in self
.ToolDefinition
.values():
1802 if ToolDef
.has_key("GUID") and ToolDef
["GUID"] == self
.Platform
.VpdToolGuid
:
1803 if not ToolDef
.has_key("PATH"):
1804 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
, "PATH attribute was not provided for BPDG guid tool %s in tools_def.txt" % self
.Platform
.VpdToolGuid
)
1805 BPDGToolName
= ToolDef
["PATH"]
1807 # Call third party GUID BPDG tool.
1808 if BPDGToolName
is not None:
1809 VpdInfoFile
.CallExtenalBPDGTool(BPDGToolName
, VpdFilePath
)
1811 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.")
1813 ## Return the platform build data object
1814 def _GetPlatform(self
):
1815 if self
._Platform
is None:
1816 self
._Platform
= self
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1817 return self
._Platform
1819 ## Return platform name
1821 return self
.Platform
.PlatformName
1823 ## Return the meta file GUID
1825 return self
.Platform
.Guid
1827 ## Return the platform version
1828 def _GetVersion(self
):
1829 return self
.Platform
.Version
1831 ## Return the FDF file name
1832 def _GetFdfFile(self
):
1833 if self
._FdfFile
is None:
1834 if self
.Workspace
.FdfFile
!= "":
1835 self
._FdfFile
= mws
.join(self
.WorkspaceDir
, self
.Workspace
.FdfFile
)
1838 return self
._FdfFile
1840 ## Return the build output directory platform specifies
1841 def _GetOutputDir(self
):
1842 return self
.Platform
.OutputDirectory
1844 ## Return the directory to store all intermediate and final files built
1845 def _GetBuildDir(self
):
1846 if self
._BuildDir
is None:
1847 if os
.path
.isabs(self
.OutputDir
):
1848 self
._BuildDir
= path
.join(
1849 path
.abspath(self
.OutputDir
),
1850 self
.BuildTarget
+ "_" + self
.ToolChain
,
1853 self
._BuildDir
= path
.join(
1856 self
.BuildTarget
+ "_" + self
.ToolChain
,
1858 GlobalData
.gBuildDirectory
= self
._BuildDir
1859 return self
._BuildDir
1861 ## Return directory of platform makefile
1863 # @retval string Makefile directory
1865 def _GetMakeFileDir(self
):
1866 if self
._MakeFileDir
is None:
1867 self
._MakeFileDir
= path
.join(self
.BuildDir
, self
.Arch
)
1868 return self
._MakeFileDir
1870 ## Return build command string
1872 # @retval string Build command string
1874 def _GetBuildCommand(self
):
1875 if self
._BuildCommand
is None:
1876 self
._BuildCommand
= []
1877 if "MAKE" in self
.ToolDefinition
and "PATH" in self
.ToolDefinition
["MAKE"]:
1878 self
._BuildCommand
+= SplitOption(self
.ToolDefinition
["MAKE"]["PATH"])
1879 if "FLAGS" in self
.ToolDefinition
["MAKE"]:
1880 NewOption
= self
.ToolDefinition
["MAKE"]["FLAGS"].strip()
1882 self
._BuildCommand
+= SplitOption(NewOption
)
1883 if "MAKE" in self
.EdkIIBuildOption
:
1884 if "FLAGS" in self
.EdkIIBuildOption
["MAKE"]:
1885 Flags
= self
.EdkIIBuildOption
["MAKE"]["FLAGS"]
1886 if Flags
.startswith('='):
1887 self
._BuildCommand
= [self
._BuildCommand
[0]] + [Flags
[1:]]
1889 self
._BuildCommand
+= [Flags
]
1890 return self
._BuildCommand
1892 ## Get tool chain definition
1894 # Get each tool defition for given tool chain from tools_def.txt and platform
1896 def _GetToolDefinition(self
):
1897 if self
._ToolDefinitions
is None:
1898 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDictionary
1899 if TAB_TOD_DEFINES_COMMAND_TYPE
not in self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
:
1900 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
, "No tools found in configuration",
1901 ExtraData
="[%s]" % self
.MetaFile
)
1902 self
._ToolDefinitions
= {}
1904 for Def
in ToolDefinition
:
1905 Target
, Tag
, Arch
, Tool
, Attr
= Def
.split("_")
1906 if Target
!= self
.BuildTarget
or Tag
!= self
.ToolChain
or Arch
!= self
.Arch
:
1909 Value
= ToolDefinition
[Def
]
1910 # don't record the DLL
1912 DllPathList
.add(Value
)
1915 if Tool
not in self
._ToolDefinitions
:
1916 self
._ToolDefinitions
[Tool
] = {}
1917 self
._ToolDefinitions
[Tool
][Attr
] = Value
1921 if GlobalData
.gOptions
.SilentMode
and "MAKE" in self
._ToolDefinitions
:
1922 if "FLAGS" not in self
._ToolDefinitions
["MAKE"]:
1923 self
._ToolDefinitions
["MAKE"]["FLAGS"] = ""
1924 self
._ToolDefinitions
["MAKE"]["FLAGS"] += " -s"
1926 for Tool
in self
._ToolDefinitions
:
1927 for Attr
in self
._ToolDefinitions
[Tool
]:
1928 Value
= self
._ToolDefinitions
[Tool
][Attr
]
1929 if Tool
in self
.BuildOption
and Attr
in self
.BuildOption
[Tool
]:
1930 # check if override is indicated
1931 if self
.BuildOption
[Tool
][Attr
].startswith('='):
1932 Value
= self
.BuildOption
[Tool
][Attr
][1:]
1935 Value
+= " " + self
.BuildOption
[Tool
][Attr
]
1937 Value
= self
.BuildOption
[Tool
][Attr
]
1940 # Don't put MAKE definition in the file
1944 ToolsDef
+= "%s = %s\n" % (Tool
, Value
)
1946 # Don't put MAKE definition in the file
1951 ToolsDef
+= "%s_%s = %s\n" % (Tool
, Attr
, Value
)
1954 SaveFileOnChange(self
.ToolDefinitionFile
, ToolsDef
)
1955 for DllPath
in DllPathList
:
1956 os
.environ
["PATH"] = DllPath
+ os
.pathsep
+ os
.environ
["PATH"]
1957 os
.environ
["MAKE_FLAGS"] = MakeFlags
1959 return self
._ToolDefinitions
1961 ## Return the paths of tools
1962 def _GetToolDefFile(self
):
1963 if self
._ToolDefFile
is None:
1964 self
._ToolDefFile
= os
.path
.join(self
.MakeFileDir
, "TOOLS_DEF." + self
.Arch
)
1965 return self
._ToolDefFile
1967 ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
1968 def _GetToolChainFamily(self
):
1969 if self
._ToolChainFamily
is None:
1970 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
1971 if TAB_TOD_DEFINES_FAMILY
not in ToolDefinition \
1972 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_FAMILY
] \
1973 or not ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]:
1974 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1976 self
._ToolChainFamily
= "MSFT"
1978 self
._ToolChainFamily
= ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]
1979 return self
._ToolChainFamily
1981 def _GetBuildRuleFamily(self
):
1982 if self
._BuildRuleFamily
is None:
1983 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
1984 if TAB_TOD_DEFINES_BUILDRULEFAMILY
not in ToolDefinition \
1985 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
] \
1986 or not ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]:
1987 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1989 self
._BuildRuleFamily
= "MSFT"
1991 self
._BuildRuleFamily
= ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]
1992 return self
._BuildRuleFamily
1994 ## Return the build options specific for all modules in this platform
1995 def _GetBuildOptions(self
):
1996 if self
._BuildOption
is None:
1997 self
._BuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
)
1998 return self
._BuildOption
2000 ## Return the build options specific for EDK modules in this platform
2001 def _GetEdkBuildOptions(self
):
2002 if self
._EdkBuildOption
is None:
2003 self
._EdkBuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDK_NAME
)
2004 return self
._EdkBuildOption
2006 ## Return the build options specific for EDKII modules in this platform
2007 def _GetEdkIIBuildOptions(self
):
2008 if self
._EdkIIBuildOption
is None:
2009 self
._EdkIIBuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDKII_NAME
)
2010 return self
._EdkIIBuildOption
2012 ## Parse build_rule.txt in Conf Directory.
2014 # @retval BuildRule object
2016 def _GetBuildRule(self
):
2017 if self
._BuildRule
is None:
2018 BuildRuleFile
= None
2019 if TAB_TAT_DEFINES_BUILD_RULE_CONF
in self
.Workspace
.TargetTxt
.TargetTxtDictionary
:
2020 BuildRuleFile
= self
.Workspace
.TargetTxt
.TargetTxtDictionary
[TAB_TAT_DEFINES_BUILD_RULE_CONF
]
2021 if BuildRuleFile
in [None, '']:
2022 BuildRuleFile
= gDefaultBuildRuleFile
2023 self
._BuildRule
= BuildRule(BuildRuleFile
)
2024 if self
._BuildRule
._FileVersion
== "":
2025 self
._BuildRule
._FileVersion
= AutoGenReqBuildRuleVerNum
2027 if self
._BuildRule
._FileVersion
< AutoGenReqBuildRuleVerNum
:
2028 # If Build Rule's version is less than the version number required by the tools, halting the build.
2029 EdkLogger
.error("build", AUTOGEN_ERROR
,
2030 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])"\
2031 % (self
._BuildRule
._FileVersion
, AutoGenReqBuildRuleVerNum
))
2033 return self
._BuildRule
2035 ## Summarize the packages used by modules in this platform
2036 def _GetPackageList(self
):
2037 if self
._PackageList
is None:
2038 self
._PackageList
= set()
2039 for La
in self
.LibraryAutoGenList
:
2040 self
._PackageList
.update(La
.DependentPackageList
)
2041 for Ma
in self
.ModuleAutoGenList
:
2042 self
._PackageList
.update(Ma
.DependentPackageList
)
2043 #Collect package set information from INF of FDF
2045 for ModuleFile
in self
._AsBuildModuleList
:
2046 if ModuleFile
in self
.Platform
.Modules
:
2048 ModuleData
= self
.BuildDatabase
[ModuleFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
2049 PkgSet
.update(ModuleData
.Packages
)
2050 self
._PackageList
= list(self
._PackageList
) + list (PkgSet
)
2051 return self
._PackageList
2053 def _GetNonDynamicPcdDict(self
):
2054 if self
._NonDynamicPcdDict
:
2055 return self
._NonDynamicPcdDict
2056 for Pcd
in self
.NonDynamicPcdList
:
2057 self
._NonDynamicPcdDict
[(Pcd
.TokenCName
,Pcd
.TokenSpaceGuidCName
)] = Pcd
2058 return self
._NonDynamicPcdDict
2060 ## Get list of non-dynamic PCDs
2061 def _GetNonDynamicPcdList(self
):
2062 if self
._NonDynamicPcdList
is None:
2063 self
.CollectPlatformDynamicPcds()
2064 return self
._NonDynamicPcdList
2066 ## Get list of dynamic PCDs
2067 def _GetDynamicPcdList(self
):
2068 if self
._DynamicPcdList
is None:
2069 self
.CollectPlatformDynamicPcds()
2070 return self
._DynamicPcdList
2072 ## Generate Token Number for all PCD
2073 def _GetPcdTokenNumbers(self
):
2074 if self
._PcdTokenNumber
is None:
2075 self
._PcdTokenNumber
= OrderedDict()
2078 # Make the Dynamic and DynamicEx PCD use within different TokenNumber area.
2082 # TokenNumber 0 ~ 10
2084 # TokeNumber 11 ~ 20
2086 for Pcd
in self
.DynamicPcdList
:
2087 if Pcd
.Phase
== "PEI":
2088 if Pcd
.Type
in ["Dynamic", "DynamicDefault", "DynamicVpd", "DynamicHii"]:
2089 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2090 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2093 for Pcd
in self
.DynamicPcdList
:
2094 if Pcd
.Phase
== "PEI":
2095 if Pcd
.Type
in ["DynamicEx", "DynamicExDefault", "DynamicExVpd", "DynamicExHii"]:
2096 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2097 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2100 for Pcd
in self
.DynamicPcdList
:
2101 if Pcd
.Phase
== "DXE":
2102 if Pcd
.Type
in ["Dynamic", "DynamicDefault", "DynamicVpd", "DynamicHii"]:
2103 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2104 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2107 for Pcd
in self
.DynamicPcdList
:
2108 if Pcd
.Phase
== "DXE":
2109 if Pcd
.Type
in ["DynamicEx", "DynamicExDefault", "DynamicExVpd", "DynamicExHii"]:
2110 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2111 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2114 for Pcd
in self
.NonDynamicPcdList
:
2115 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2117 return self
._PcdTokenNumber
2119 ## Summarize ModuleAutoGen objects of all modules/libraries to be built for this platform
2120 def _GetAutoGenObjectList(self
):
2121 self
._ModuleAutoGenList
= []
2122 self
._LibraryAutoGenList
= []
2123 for ModuleFile
in self
.Platform
.Modules
:
2132 if Ma
not in self
._ModuleAutoGenList
:
2133 self
._ModuleAutoGenList
.append(Ma
)
2134 for La
in Ma
.LibraryAutoGenList
:
2135 if La
not in self
._LibraryAutoGenList
:
2136 self
._LibraryAutoGenList
.append(La
)
2137 if Ma
not in La
._ReferenceModules
:
2138 La
._ReferenceModules
.append(Ma
)
2140 ## Summarize ModuleAutoGen objects of all modules to be built for this platform
2141 def _GetModuleAutoGenList(self
):
2142 if self
._ModuleAutoGenList
is None:
2143 self
._GetAutoGenObjectList
()
2144 return self
._ModuleAutoGenList
2146 ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
2147 def _GetLibraryAutoGenList(self
):
2148 if self
._LibraryAutoGenList
is None:
2149 self
._GetAutoGenObjectList
()
2150 return self
._LibraryAutoGenList
2152 ## Test if a module is supported by the platform
2154 # An error will be raised directly if the module or its arch is not supported
2155 # by the platform or current configuration
2157 def ValidModule(self
, Module
):
2158 return Module
in self
.Platform
.Modules
or Module
in self
.Platform
.LibraryInstances \
2159 or Module
in self
._AsBuildModuleList
2161 ## Resolve the library classes in a module to library instances
2163 # This method will not only resolve library classes but also sort the library
2164 # instances according to the dependency-ship.
2166 # @param Module The module from which the library classes will be resolved
2168 # @retval library_list List of library instances sorted
2170 def ApplyLibraryInstance(self
, Module
):
2171 # Cover the case that the binary INF file is list in the FDF file but not DSC file, return empty list directly
2172 if str(Module
) not in self
.Platform
.Modules
:
2175 ModuleType
= Module
.ModuleType
2177 # for overridding library instances with module specific setting
2178 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
2180 # add forced library instances (specified under LibraryClasses sections)
2182 # If a module has a MODULE_TYPE of USER_DEFINED,
2183 # do not link in NULL library class instances from the global [LibraryClasses.*] sections.
2185 if Module
.ModuleType
!= SUP_MODULE_USER_DEFINED
:
2186 for LibraryClass
in self
.Platform
.LibraryClasses
.GetKeys():
2187 if LibraryClass
.startswith("NULL") and self
.Platform
.LibraryClasses
[LibraryClass
, Module
.ModuleType
]:
2188 Module
.LibraryClasses
[LibraryClass
] = self
.Platform
.LibraryClasses
[LibraryClass
, Module
.ModuleType
]
2190 # add forced library instances (specified in module overrides)
2191 for LibraryClass
in PlatformModule
.LibraryClasses
:
2192 if LibraryClass
.startswith("NULL"):
2193 Module
.LibraryClasses
[LibraryClass
] = PlatformModule
.LibraryClasses
[LibraryClass
]
2196 LibraryConsumerList
= [Module
]
2198 ConsumedByList
= OrderedDict()
2199 LibraryInstance
= OrderedDict()
2201 EdkLogger
.verbose("")
2202 EdkLogger
.verbose("Library instances of module [%s] [%s]:" % (str(Module
), self
.Arch
))
2203 while len(LibraryConsumerList
) > 0:
2204 M
= LibraryConsumerList
.pop()
2205 for LibraryClassName
in M
.LibraryClasses
:
2206 if LibraryClassName
not in LibraryInstance
:
2207 # override library instance for this module
2208 if LibraryClassName
in PlatformModule
.LibraryClasses
:
2209 LibraryPath
= PlatformModule
.LibraryClasses
[LibraryClassName
]
2211 LibraryPath
= self
.Platform
.LibraryClasses
[LibraryClassName
, ModuleType
]
2212 if LibraryPath
is None or LibraryPath
== "":
2213 LibraryPath
= M
.LibraryClasses
[LibraryClassName
]
2214 if LibraryPath
is None or LibraryPath
== "":
2215 EdkLogger
.error("build", RESOURCE_NOT_AVAILABLE
,
2216 "Instance of library class [%s] is not found" % LibraryClassName
,
2218 ExtraData
="in [%s] [%s]\n\tconsumed by module [%s]" % (str(M
), self
.Arch
, str(Module
)))
2220 LibraryModule
= self
.BuildDatabase
[LibraryPath
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
2221 # for those forced library instance (NULL library), add a fake library class
2222 if LibraryClassName
.startswith("NULL"):
2223 LibraryModule
.LibraryClass
.append(LibraryClassObject(LibraryClassName
, [ModuleType
]))
2224 elif LibraryModule
.LibraryClass
is None \
2225 or len(LibraryModule
.LibraryClass
) == 0 \
2226 or (ModuleType
!= 'USER_DEFINED'
2227 and ModuleType
not in LibraryModule
.LibraryClass
[0].SupModList
):
2228 # only USER_DEFINED can link against any library instance despite of its SupModList
2229 EdkLogger
.error("build", OPTION_MISSING
,
2230 "Module type [%s] is not supported by library instance [%s]" \
2231 % (ModuleType
, LibraryPath
), File
=self
.MetaFile
,
2232 ExtraData
="consumed by [%s]" % str(Module
))
2234 LibraryInstance
[LibraryClassName
] = LibraryModule
2235 LibraryConsumerList
.append(LibraryModule
)
2236 EdkLogger
.verbose("\t" + str(LibraryClassName
) + " : " + str(LibraryModule
))
2238 LibraryModule
= LibraryInstance
[LibraryClassName
]
2240 if LibraryModule
is None:
2243 if LibraryModule
.ConstructorList
!= [] and LibraryModule
not in Constructor
:
2244 Constructor
.append(LibraryModule
)
2246 if LibraryModule
not in ConsumedByList
:
2247 ConsumedByList
[LibraryModule
] = []
2248 # don't add current module itself to consumer list
2250 if M
in ConsumedByList
[LibraryModule
]:
2252 ConsumedByList
[LibraryModule
].append(M
)
2254 # Initialize the sorted output list to the empty set
2256 SortedLibraryList
= []
2258 # Q <- Set of all nodes with no incoming edges
2260 LibraryList
= [] #LibraryInstance.values()
2262 for LibraryClassName
in LibraryInstance
:
2263 M
= LibraryInstance
[LibraryClassName
]
2264 LibraryList
.append(M
)
2265 if ConsumedByList
[M
] == []:
2269 # start the DAG algorithm
2273 while Q
== [] and EdgeRemoved
:
2275 # for each node Item with a Constructor
2276 for Item
in LibraryList
:
2277 if Item
not in Constructor
:
2279 # for each Node without a constructor with an edge e from Item to Node
2280 for Node
in ConsumedByList
[Item
]:
2281 if Node
in Constructor
:
2283 # remove edge e from the graph if Node has no constructor
2284 ConsumedByList
[Item
].remove(Node
)
2286 if ConsumedByList
[Item
] == []:
2287 # insert Item into Q
2292 # DAG is done if there's no more incoming edge for all nodes
2296 # remove node from Q
2299 SortedLibraryList
.append(Node
)
2301 # for each node Item with an edge e from Node to Item do
2302 for Item
in LibraryList
:
2303 if Node
not in ConsumedByList
[Item
]:
2305 # remove edge e from the graph
2306 ConsumedByList
[Item
].remove(Node
)
2308 if ConsumedByList
[Item
] != []:
2310 # insert Item into Q, if Item has no other incoming edges
2314 # if any remaining node Item in the graph has a constructor and an incoming edge, then the graph has a cycle
2316 for Item
in LibraryList
:
2317 if ConsumedByList
[Item
] != [] and Item
in Constructor
and len(Constructor
) > 1:
2318 ErrorMessage
= "\tconsumed by " + "\n\tconsumed by ".join([str(L
) for L
in ConsumedByList
[Item
]])
2319 EdkLogger
.error("build", BUILD_ERROR
, 'Library [%s] with constructors has a cycle' % str(Item
),
2320 ExtraData
=ErrorMessage
, File
=self
.MetaFile
)
2321 if Item
not in SortedLibraryList
:
2322 SortedLibraryList
.append(Item
)
2325 # Build the list of constructor and destructir names
2326 # The DAG Topo sort produces the destructor order, so the list of constructors must generated in the reverse order
2328 SortedLibraryList
.reverse()
2329 return SortedLibraryList
2332 ## Override PCD setting (type, value, ...)
2334 # @param ToPcd The PCD to be overrided
2335 # @param FromPcd The PCD overrideing from
2337 def _OverridePcd(self
, ToPcd
, FromPcd
, Module
=""):
2339 # in case there's PCDs coming from FDF file, which have no type given.
2340 # at this point, ToPcd.Type has the type found from dependent
2343 TokenCName
= ToPcd
.TokenCName
2344 for PcdItem
in GlobalData
.MixedPcd
:
2345 if (ToPcd
.TokenCName
, ToPcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
2346 TokenCName
= PcdItem
[0]
2348 if FromPcd
is not None:
2349 if ToPcd
.Pending
and FromPcd
.Type
not in [None, '']:
2350 ToPcd
.Type
= FromPcd
.Type
2351 elif (ToPcd
.Type
not in [None, '']) and (FromPcd
.Type
not in [None, ''])\
2352 and (ToPcd
.Type
!= FromPcd
.Type
) and (ToPcd
.Type
in FromPcd
.Type
):
2353 if ToPcd
.Type
.strip() == "DynamicEx":
2354 ToPcd
.Type
= FromPcd
.Type
2355 elif ToPcd
.Type
not in [None, ''] and FromPcd
.Type
not in [None, ''] \
2356 and ToPcd
.Type
!= FromPcd
.Type
:
2357 EdkLogger
.error("build", OPTION_CONFLICT
, "Mismatched PCD type",
2358 ExtraData
="%s.%s is defined as [%s] in module %s, but as [%s] in platform."\
2359 % (ToPcd
.TokenSpaceGuidCName
, TokenCName
,
2360 ToPcd
.Type
, Module
, FromPcd
.Type
),
2363 if FromPcd
.MaxDatumSize
not in [None, '']:
2364 ToPcd
.MaxDatumSize
= FromPcd
.MaxDatumSize
2365 if FromPcd
.DefaultValue
not in [None, '']:
2366 ToPcd
.DefaultValue
= FromPcd
.DefaultValue
2367 if FromPcd
.TokenValue
not in [None, '']:
2368 ToPcd
.TokenValue
= FromPcd
.TokenValue
2369 if FromPcd
.MaxDatumSize
not in [None, '']:
2370 ToPcd
.MaxDatumSize
= FromPcd
.MaxDatumSize
2371 if FromPcd
.DatumType
not in [None, '']:
2372 ToPcd
.DatumType
= FromPcd
.DatumType
2373 if FromPcd
.SkuInfoList
not in [None, '', []]:
2374 ToPcd
.SkuInfoList
= FromPcd
.SkuInfoList
2375 # Add Flexible PCD format parse
2376 if ToPcd
.DefaultValue
:
2378 ToPcd
.DefaultValue
= ValueExpressionEx(ToPcd
.DefaultValue
, ToPcd
.DatumType
, self
._GuidDict
)(True)
2379 except BadExpression
, Value
:
2380 EdkLogger
.error('Parser', FORMAT_INVALID
, 'PCD [%s.%s] Value "%s", %s' %(ToPcd
.TokenSpaceGuidCName
, ToPcd
.TokenCName
, ToPcd
.DefaultValue
, Value
),
2383 # check the validation of datum
2384 IsValid
, Cause
= CheckPcdDatum(ToPcd
.DatumType
, ToPcd
.DefaultValue
)
2386 EdkLogger
.error('build', FORMAT_INVALID
, Cause
, File
=self
.MetaFile
,
2387 ExtraData
="%s.%s" % (ToPcd
.TokenSpaceGuidCName
, TokenCName
))
2388 ToPcd
.validateranges
= FromPcd
.validateranges
2389 ToPcd
.validlists
= FromPcd
.validlists
2390 ToPcd
.expressions
= FromPcd
.expressions
2392 if FromPcd
is not None and ToPcd
.DatumType
== "VOID*" and ToPcd
.MaxDatumSize
in ['', None]:
2393 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "No MaxDatumSize specified for PCD %s.%s" \
2394 % (ToPcd
.TokenSpaceGuidCName
, TokenCName
))
2395 Value
= ToPcd
.DefaultValue
2396 if Value
in [None, '']:
2397 ToPcd
.MaxDatumSize
= '1'
2398 elif Value
[0] == 'L':
2399 ToPcd
.MaxDatumSize
= str((len(Value
) - 2) * 2)
2400 elif Value
[0] == '{':
2401 ToPcd
.MaxDatumSize
= str(len(Value
.split(',')))
2403 ToPcd
.MaxDatumSize
= str(len(Value
) - 1)
2405 # apply default SKU for dynamic PCDS if specified one is not available
2406 if (ToPcd
.Type
in PCD_DYNAMIC_TYPE_LIST
or ToPcd
.Type
in PCD_DYNAMIC_EX_TYPE_LIST
) \
2407 and ToPcd
.SkuInfoList
in [None, {}, '']:
2408 if self
.Platform
.SkuName
in self
.Platform
.SkuIds
:
2409 SkuName
= self
.Platform
.SkuName
2412 ToPcd
.SkuInfoList
= {
2413 SkuName
: SkuInfoClass(SkuName
, self
.Platform
.SkuIds
[SkuName
][0], '', '', '', '', '', ToPcd
.DefaultValue
)
2416 ## Apply PCD setting defined platform to a module
2418 # @param Module The module from which the PCD setting will be overrided
2420 # @retval PCD_list The list PCDs with settings from platform
2422 def ApplyPcdSetting(self
, Module
, Pcds
):
2423 # for each PCD in module
2424 for Name
, Guid
in Pcds
:
2425 PcdInModule
= Pcds
[Name
, Guid
]
2426 # find out the PCD setting in platform
2427 if (Name
, Guid
) in self
.Platform
.Pcds
:
2428 PcdInPlatform
= self
.Platform
.Pcds
[Name
, Guid
]
2430 PcdInPlatform
= None
2431 # then override the settings if any
2432 self
._OverridePcd
(PcdInModule
, PcdInPlatform
, Module
)
2433 # resolve the VariableGuid value
2434 for SkuId
in PcdInModule
.SkuInfoList
:
2435 Sku
= PcdInModule
.SkuInfoList
[SkuId
]
2436 if Sku
.VariableGuid
== '': continue
2437 Sku
.VariableGuidValue
= GuidValue(Sku
.VariableGuid
, self
.PackageList
, self
.MetaFile
.Path
)
2438 if Sku
.VariableGuidValue
is None:
2439 PackageList
= "\n\t".join([str(P
) for P
in self
.PackageList
])
2442 RESOURCE_NOT_AVAILABLE
,
2443 "Value of GUID [%s] is not found in" % Sku
.VariableGuid
,
2444 ExtraData
=PackageList
+ "\n\t(used with %s.%s from module %s)" \
2445 % (Guid
, Name
, str(Module
)),
2449 # override PCD settings with module specific setting
2450 if Module
in self
.Platform
.Modules
:
2451 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
2452 for Key
in PlatformModule
.Pcds
:
2457 elif Key
in GlobalData
.MixedPcd
:
2458 for PcdItem
in GlobalData
.MixedPcd
[Key
]:
2460 ToPcd
= Pcds
[PcdItem
]
2464 self
._OverridePcd
(ToPcd
, PlatformModule
.Pcds
[Key
], Module
)
2465 # use PCD value to calculate the MaxDatumSize when it is not specified
2466 for Name
, Guid
in Pcds
:
2467 Pcd
= Pcds
[Name
, Guid
]
2468 if Pcd
.DatumType
== "VOID*" and Pcd
.MaxDatumSize
in ['', None]:
2469 Value
= Pcd
.DefaultValue
2470 if Value
in [None, '']:
2471 Pcd
.MaxDatumSize
= '1'
2472 elif Value
[0] == 'L':
2473 Pcd
.MaxDatumSize
= str((len(Value
) - 2) * 2)
2474 elif Value
[0] == '{':
2475 Pcd
.MaxDatumSize
= str(len(Value
.split(',')))
2477 Pcd
.MaxDatumSize
= str(len(Value
) - 1)
2478 return Pcds
.values()
2480 ## Resolve library names to library modules
2482 # (for Edk.x modules)
2484 # @param Module The module from which the library names will be resolved
2486 # @retval library_list The list of library modules
2488 def ResolveLibraryReference(self
, Module
):
2489 EdkLogger
.verbose("")
2490 EdkLogger
.verbose("Library instances of module [%s] [%s]:" % (str(Module
), self
.Arch
))
2491 LibraryConsumerList
= [Module
]
2493 # "CompilerStub" is a must for Edk modules
2494 if Module
.Libraries
:
2495 Module
.Libraries
.append("CompilerStub")
2497 while len(LibraryConsumerList
) > 0:
2498 M
= LibraryConsumerList
.pop()
2499 for LibraryName
in M
.Libraries
:
2500 Library
= self
.Platform
.LibraryClasses
[LibraryName
, ':dummy:']
2502 for Key
in self
.Platform
.LibraryClasses
.data
.keys():
2503 if LibraryName
.upper() == Key
.upper():
2504 Library
= self
.Platform
.LibraryClasses
[Key
, ':dummy:']
2507 EdkLogger
.warn("build", "Library [%s] is not found" % LibraryName
, File
=str(M
),
2508 ExtraData
="\t%s [%s]" % (str(Module
), self
.Arch
))
2511 if Library
not in LibraryList
:
2512 LibraryList
.append(Library
)
2513 LibraryConsumerList
.append(Library
)
2514 EdkLogger
.verbose("\t" + LibraryName
+ " : " + str(Library
) + ' ' + str(type(Library
)))
2517 ## Calculate the priority value of the build option
2519 # @param Key Build option definition contain: TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
2521 # @retval Value Priority value based on the priority list.
2523 def CalculatePriorityValue(self
, Key
):
2524 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
.split('_')
2525 PriorityValue
= 0x11111
2527 PriorityValue
&= 0x01111
2528 if ToolChain
== "*":
2529 PriorityValue
&= 0x10111
2531 PriorityValue
&= 0x11011
2532 if CommandType
== "*":
2533 PriorityValue
&= 0x11101
2535 PriorityValue
&= 0x11110
2537 return self
.PrioList
["0x%0.5x" % PriorityValue
]
2540 ## Expand * in build option key
2542 # @param Options Options to be expanded
2544 # @retval options Options expanded
2546 def _ExpandBuildOption(self
, Options
, ModuleStyle
=None):
2553 # Construct a list contain the build options which need override.
2557 # Key[0] -- tool family
2558 # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
2560 if (Key
[0] == self
.BuildRuleFamily
and
2561 (ModuleStyle
is None or len(Key
) < 3 or (len(Key
) > 2 and Key
[2] == ModuleStyle
))):
2562 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
[1].split('_')
2563 if Target
== self
.BuildTarget
or Target
== "*":
2564 if ToolChain
== self
.ToolChain
or ToolChain
== "*":
2565 if Arch
== self
.Arch
or Arch
== "*":
2566 if Options
[Key
].startswith("="):
2567 if OverrideList
.get(Key
[1]) is not None:
2568 OverrideList
.pop(Key
[1])
2569 OverrideList
[Key
[1]] = Options
[Key
]
2572 # Use the highest priority value.
2574 if (len(OverrideList
) >= 2):
2575 KeyList
= OverrideList
.keys()
2576 for Index
in range(len(KeyList
)):
2577 NowKey
= KeyList
[Index
]
2578 Target1
, ToolChain1
, Arch1
, CommandType1
, Attr1
= NowKey
.split("_")
2579 for Index1
in range(len(KeyList
) - Index
- 1):
2580 NextKey
= KeyList
[Index1
+ Index
+ 1]
2582 # Compare two Key, if one is included by another, choose the higher priority one
2584 Target2
, ToolChain2
, Arch2
, CommandType2
, Attr2
= NextKey
.split("_")
2585 if Target1
== Target2
or Target1
== "*" or Target2
== "*":
2586 if ToolChain1
== ToolChain2
or ToolChain1
== "*" or ToolChain2
== "*":
2587 if Arch1
== Arch2
or Arch1
== "*" or Arch2
== "*":
2588 if CommandType1
== CommandType2
or CommandType1
== "*" or CommandType2
== "*":
2589 if Attr1
== Attr2
or Attr1
== "*" or Attr2
== "*":
2590 if self
.CalculatePriorityValue(NowKey
) > self
.CalculatePriorityValue(NextKey
):
2591 if Options
.get((self
.BuildRuleFamily
, NextKey
)) is not None:
2592 Options
.pop((self
.BuildRuleFamily
, NextKey
))
2594 if Options
.get((self
.BuildRuleFamily
, NowKey
)) is not None:
2595 Options
.pop((self
.BuildRuleFamily
, NowKey
))
2598 if ModuleStyle
is not None and len (Key
) > 2:
2599 # Check Module style is EDK or EDKII.
2600 # Only append build option for the matched style module.
2601 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
2603 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
2606 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
2607 # if tool chain family doesn't match, skip it
2608 if Tool
in self
.ToolDefinition
and Family
!= "":
2609 FamilyIsNull
= False
2610 if self
.ToolDefinition
[Tool
].get(TAB_TOD_DEFINES_BUILDRULEFAMILY
, "") != "":
2611 if Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_BUILDRULEFAMILY
]:
2613 elif Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
2616 # expand any wildcard
2617 if Target
== "*" or Target
== self
.BuildTarget
:
2618 if Tag
== "*" or Tag
== self
.ToolChain
:
2619 if Arch
== "*" or Arch
== self
.Arch
:
2620 if Tool
not in BuildOptions
:
2621 BuildOptions
[Tool
] = {}
2622 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
] or Options
[Key
].startswith('='):
2623 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2625 # append options for the same tool except PATH
2627 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
2629 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2630 # Build Option Family has been checked, which need't to be checked again for family.
2631 if FamilyMatch
or FamilyIsNull
:
2635 if ModuleStyle
is not None and len (Key
) > 2:
2636 # Check Module style is EDK or EDKII.
2637 # Only append build option for the matched style module.
2638 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
2640 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
2643 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
2644 # if tool chain family doesn't match, skip it
2645 if Tool
not in self
.ToolDefinition
or Family
== "":
2647 # option has been added before
2648 if Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
2651 # expand any wildcard
2652 if Target
== "*" or Target
== self
.BuildTarget
:
2653 if Tag
== "*" or Tag
== self
.ToolChain
:
2654 if Arch
== "*" or Arch
== self
.Arch
:
2655 if Tool
not in BuildOptions
:
2656 BuildOptions
[Tool
] = {}
2657 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
] or Options
[Key
].startswith('='):
2658 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2660 # append options for the same tool except PATH
2662 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
2664 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2667 ## Append build options in platform to a module
2669 # @param Module The module to which the build options will be appened
2671 # @retval options The options appended with build options in platform
2673 def ApplyBuildOption(self
, Module
):
2674 # Get the different options for the different style module
2675 if Module
.AutoGenVersion
< 0x00010005:
2676 PlatformOptions
= self
.EdkBuildOption
2677 ModuleTypeOptions
= self
.Platform
.GetBuildOptionsByModuleType(EDK_NAME
, Module
.ModuleType
)
2679 PlatformOptions
= self
.EdkIIBuildOption
2680 ModuleTypeOptions
= self
.Platform
.GetBuildOptionsByModuleType(EDKII_NAME
, Module
.ModuleType
)
2681 ModuleTypeOptions
= self
._ExpandBuildOption
(ModuleTypeOptions
)
2682 ModuleOptions
= self
._ExpandBuildOption
(Module
.BuildOptions
)
2683 if Module
in self
.Platform
.Modules
:
2684 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
2685 PlatformModuleOptions
= self
._ExpandBuildOption
(PlatformModule
.BuildOptions
)
2687 PlatformModuleOptions
= {}
2689 BuildRuleOrder
= None
2690 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, ModuleTypeOptions
, PlatformModuleOptions
]:
2691 for Tool
in Options
:
2692 for Attr
in Options
[Tool
]:
2693 if Attr
== TAB_TOD_DEFINES_BUILDRULEORDER
:
2694 BuildRuleOrder
= Options
[Tool
][Attr
]
2696 AllTools
= set(ModuleOptions
.keys() + PlatformOptions
.keys() +
2697 PlatformModuleOptions
.keys() + ModuleTypeOptions
.keys() +
2698 self
.ToolDefinition
.keys())
2700 for Tool
in AllTools
:
2701 if Tool
not in BuildOptions
:
2702 BuildOptions
[Tool
] = {}
2704 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, ModuleTypeOptions
, PlatformModuleOptions
]:
2705 if Tool
not in Options
:
2707 for Attr
in Options
[Tool
]:
2708 Value
= Options
[Tool
][Attr
]
2710 # Do not generate it in Makefile
2712 if Attr
== TAB_TOD_DEFINES_BUILDRULEORDER
:
2714 if Attr
not in BuildOptions
[Tool
]:
2715 BuildOptions
[Tool
][Attr
] = ""
2716 # check if override is indicated
2717 if Value
.startswith('='):
2718 ToolPath
= Value
[1:]
2719 ToolPath
= mws
.handleWsMacro(ToolPath
)
2720 BuildOptions
[Tool
][Attr
] = ToolPath
2722 Value
= mws
.handleWsMacro(Value
)
2724 BuildOptions
[Tool
][Attr
] += " " + Value
2726 BuildOptions
[Tool
][Attr
] = Value
2727 if Module
.AutoGenVersion
< 0x00010005 and self
.Workspace
.UniFlag
is not None:
2729 # Override UNI flag only for EDK module.
2731 if 'BUILD' not in BuildOptions
:
2732 BuildOptions
['BUILD'] = {}
2733 BuildOptions
['BUILD']['FLAGS'] = self
.Workspace
.UniFlag
2734 return BuildOptions
, BuildRuleOrder
2736 Platform
= property(_GetPlatform
)
2737 Name
= property(_GetName
)
2738 Guid
= property(_GetGuid
)
2739 Version
= property(_GetVersion
)
2741 OutputDir
= property(_GetOutputDir
)
2742 BuildDir
= property(_GetBuildDir
)
2743 MakeFileDir
= property(_GetMakeFileDir
)
2744 FdfFile
= property(_GetFdfFile
)
2746 PcdTokenNumber
= property(_GetPcdTokenNumbers
) # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
2747 DynamicPcdList
= property(_GetDynamicPcdList
) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
2748 NonDynamicPcdList
= property(_GetNonDynamicPcdList
) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
2749 NonDynamicPcdDict
= property(_GetNonDynamicPcdDict
)
2750 PackageList
= property(_GetPackageList
)
2752 ToolDefinition
= property(_GetToolDefinition
) # toolcode : tool path
2753 ToolDefinitionFile
= property(_GetToolDefFile
) # toolcode : lib path
2754 ToolChainFamily
= property(_GetToolChainFamily
)
2755 BuildRuleFamily
= property(_GetBuildRuleFamily
)
2756 BuildOption
= property(_GetBuildOptions
) # toolcode : option
2757 EdkBuildOption
= property(_GetEdkBuildOptions
) # edktoolcode : option
2758 EdkIIBuildOption
= property(_GetEdkIIBuildOptions
) # edkiitoolcode : option
2760 BuildCommand
= property(_GetBuildCommand
)
2761 BuildRule
= property(_GetBuildRule
)
2762 ModuleAutoGenList
= property(_GetModuleAutoGenList
)
2763 LibraryAutoGenList
= property(_GetLibraryAutoGenList
)
2764 GenFdsCommand
= property(_GenFdsCommand
)
2766 ## ModuleAutoGen class
2768 # This class encapsules the AutoGen behaviors for the build tools. In addition to
2769 # the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according
2770 # to the [depex] section in module's inf file.
2772 class ModuleAutoGen(AutoGen
):
2773 # call super().__init__ then call the worker function with different parameter count
2774 def __init__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
2778 super(ModuleAutoGen
, self
).__init
__(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
2779 self
._InitWorker
(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
)
2782 ## Cache the timestamps of metafiles of every module in a class variable
2786 def __new__(cls
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
2787 obj
= super(ModuleAutoGen
, cls
).__new
__(cls
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
2788 # check if this module is employed by active platform
2789 if not PlatformAutoGen(Workspace
, args
[0], Target
, Toolchain
, Arch
).ValidModule(MetaFile
):
2790 EdkLogger
.verbose("Module [%s] for [%s] is not employed by active platform\n" \
2795 ## Initialize ModuleAutoGen
2797 # @param Workspace EdkIIWorkspaceBuild object
2798 # @param ModuleFile The path of module file
2799 # @param Target Build target (DEBUG, RELEASE)
2800 # @param Toolchain Name of tool chain
2801 # @param Arch The arch the module supports
2802 # @param PlatformFile Platform meta-file
2804 def _InitWorker(self
, Workspace
, ModuleFile
, Target
, Toolchain
, Arch
, PlatformFile
):
2805 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen module [%s] [%s]" % (ModuleFile
, Arch
))
2806 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (ModuleFile
, Arch
, Toolchain
, Target
)
2808 self
.Workspace
= Workspace
2809 self
.WorkspaceDir
= Workspace
.WorkspaceDir
2811 self
.MetaFile
= ModuleFile
2812 self
.PlatformInfo
= PlatformAutoGen(Workspace
, PlatformFile
, Target
, Toolchain
, Arch
)
2814 self
.SourceDir
= self
.MetaFile
.SubDir
2815 self
.SourceDir
= mws
.relpath(self
.SourceDir
, self
.WorkspaceDir
)
2817 self
.SourceOverrideDir
= None
2818 # use overrided path defined in DSC file
2819 if self
.MetaFile
.Key
in GlobalData
.gOverrideDir
:
2820 self
.SourceOverrideDir
= GlobalData
.gOverrideDir
[self
.MetaFile
.Key
]
2822 self
.ToolChain
= Toolchain
2823 self
.BuildTarget
= Target
2825 self
.ToolChainFamily
= self
.PlatformInfo
.ToolChainFamily
2826 self
.BuildRuleFamily
= self
.PlatformInfo
.BuildRuleFamily
2828 self
.IsMakeFileCreated
= False
2829 self
.IsCodeFileCreated
= False
2830 self
.IsAsBuiltInfCreated
= False
2831 self
.DepexGenerated
= False
2833 self
.BuildDatabase
= self
.Workspace
.BuildDatabase
2834 self
.BuildRuleOrder
= None
2840 self
._Version
= None
2841 self
._ModuleType
= None
2842 self
._ComponentType
= None
2843 self
._PcdIsDriver
= None
2844 self
._AutoGenVersion
= None
2845 self
._LibraryFlag
= None
2846 self
._CustomMakefile
= None
2849 self
._BuildDir
= None
2850 self
._OutputDir
= None
2851 self
._FfsOutputDir
= None
2852 self
._DebugDir
= None
2853 self
._MakeFileDir
= None
2855 self
._IncludePathList
= None
2856 self
._IncludePathLength
= 0
2857 self
._AutoGenFileList
= None
2858 self
._UnicodeFileList
= None
2859 self
._VfrFileList
= None
2860 self
._IdfFileList
= None
2861 self
._SourceFileList
= None
2862 self
._ObjectFileList
= None
2863 self
._BinaryFileList
= None
2865 self
._DependentPackageList
= None
2866 self
._DependentLibraryList
= None
2867 self
._LibraryAutoGenList
= None
2868 self
._DerivedPackageList
= None
2869 self
._ModulePcdList
= None
2870 self
._LibraryPcdList
= None
2871 self
._PcdComments
= OrderedDict()
2872 self
._GuidList
= None
2873 self
._GuidsUsedByPcd
= None
2874 self
._GuidComments
= OrderedDict()
2875 self
._ProtocolList
= None
2876 self
._ProtocolComments
= OrderedDict()
2877 self
._PpiList
= None
2878 self
._PpiComments
= OrderedDict()
2879 self
._DepexList
= None
2880 self
._DepexExpressionList
= None
2881 self
._BuildOption
= None
2882 self
._BuildOptionIncPathList
= None
2883 self
._BuildTargets
= None
2884 self
._IntroBuildTargetList
= None
2885 self
._FinalBuildTargetList
= None
2886 self
._FileTypes
= None
2887 self
._BuildRules
= None
2889 self
._TimeStampPath
= None
2891 self
.AutoGenDepSet
= set()
2894 ## The Modules referenced to this Library
2895 # Only Library has this attribute
2896 self
._ReferenceModules
= []
2898 ## Store the FixedAtBuild Pcds
2900 self
._FixedAtBuildPcds
= []
2905 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
2907 # Get FixedAtBuild Pcds of this Module
2908 def _GetFixedAtBuildPcds(self
):
2909 if self
._FixedAtBuildPcds
:
2910 return self
._FixedAtBuildPcds
2911 for Pcd
in self
.ModulePcdList
:
2912 if Pcd
.Type
!= "FixedAtBuild":
2914 if Pcd
not in self
._FixedAtBuildPcds
:
2915 self
._FixedAtBuildPcds
.append(Pcd
)
2917 return self
._FixedAtBuildPcds
2919 def _GetUniqueBaseName(self
):
2920 BaseName
= self
.Name
2921 for Module
in self
.PlatformInfo
.ModuleAutoGenList
:
2922 if Module
.MetaFile
== self
.MetaFile
:
2924 if Module
.Name
== self
.Name
:
2925 if uuid
.UUID(Module
.Guid
) == uuid
.UUID(self
.Guid
):
2926 EdkLogger
.error("build", FILE_DUPLICATED
, 'Modules have same BaseName and FILE_GUID:\n'
2927 ' %s\n %s' % (Module
.MetaFile
, self
.MetaFile
))
2928 BaseName
= '%s_%s' % (self
.Name
, self
.Guid
)
2931 # Macros could be used in build_rule.txt (also Makefile)
2932 def _GetMacros(self
):
2933 if self
._Macro
is None:
2934 self
._Macro
= OrderedDict()
2935 self
._Macro
["WORKSPACE" ] = self
.WorkspaceDir
2936 self
._Macro
["MODULE_NAME" ] = self
.Name
2937 self
._Macro
["MODULE_NAME_GUID" ] = self
._GetUniqueBaseName
()
2938 self
._Macro
["MODULE_GUID" ] = self
.Guid
2939 self
._Macro
["MODULE_VERSION" ] = self
.Version
2940 self
._Macro
["MODULE_TYPE" ] = self
.ModuleType
2941 self
._Macro
["MODULE_FILE" ] = str(self
.MetaFile
)
2942 self
._Macro
["MODULE_FILE_BASE_NAME" ] = self
.MetaFile
.BaseName
2943 self
._Macro
["MODULE_RELATIVE_DIR" ] = self
.SourceDir
2944 self
._Macro
["MODULE_DIR" ] = self
.SourceDir
2946 self
._Macro
["BASE_NAME" ] = self
.Name
2948 self
._Macro
["ARCH" ] = self
.Arch
2949 self
._Macro
["TOOLCHAIN" ] = self
.ToolChain
2950 self
._Macro
["TOOLCHAIN_TAG" ] = self
.ToolChain
2951 self
._Macro
["TOOL_CHAIN_TAG" ] = self
.ToolChain
2952 self
._Macro
["TARGET" ] = self
.BuildTarget
2954 self
._Macro
["BUILD_DIR" ] = self
.PlatformInfo
.BuildDir
2955 self
._Macro
["BIN_DIR" ] = os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)
2956 self
._Macro
["LIB_DIR" ] = os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)
2957 self
._Macro
["MODULE_BUILD_DIR" ] = self
.BuildDir
2958 self
._Macro
["OUTPUT_DIR" ] = self
.OutputDir
2959 self
._Macro
["DEBUG_DIR" ] = self
.DebugDir
2960 self
._Macro
["DEST_DIR_OUTPUT" ] = self
.OutputDir
2961 self
._Macro
["DEST_DIR_DEBUG" ] = self
.DebugDir
2962 self
._Macro
["PLATFORM_NAME" ] = self
.PlatformInfo
.Name
2963 self
._Macro
["PLATFORM_GUID" ] = self
.PlatformInfo
.Guid
2964 self
._Macro
["PLATFORM_VERSION" ] = self
.PlatformInfo
.Version
2965 self
._Macro
["PLATFORM_RELATIVE_DIR" ] = self
.PlatformInfo
.SourceDir
2966 self
._Macro
["PLATFORM_DIR" ] = mws
.join(self
.WorkspaceDir
, self
.PlatformInfo
.SourceDir
)
2967 self
._Macro
["PLATFORM_OUTPUT_DIR" ] = self
.PlatformInfo
.OutputDir
2968 self
._Macro
["FFS_OUTPUT_DIR" ] = self
.FfsOutputDir
2971 ## Return the module build data object
2972 def _GetModule(self
):
2973 if self
._Module
is None:
2974 self
._Module
= self
.Workspace
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
2977 ## Return the module name
2978 def _GetBaseName(self
):
2979 return self
.Module
.BaseName
2981 ## Return the module DxsFile if exist
2982 def _GetDxsFile(self
):
2983 return self
.Module
.DxsFile
2985 ## Return the module SourceOverridePath
2986 def _GetSourceOverridePath(self
):
2987 return self
.Module
.SourceOverridePath
2989 ## Return the module meta-file GUID
2992 # To build same module more than once, the module path with FILE_GUID overridden has
2993 # the file name FILE_GUIDmodule.inf, but the relative path (self.MetaFile.File) is the realy path
2994 # in DSC. The overridden GUID can be retrieved from file name
2996 if os
.path
.basename(self
.MetaFile
.File
) != os
.path
.basename(self
.MetaFile
.Path
):
2998 # Length of GUID is 36
3000 return os
.path
.basename(self
.MetaFile
.Path
)[:36]
3001 return self
.Module
.Guid
3003 ## Return the module version
3004 def _GetVersion(self
):
3005 return self
.Module
.Version
3007 ## Return the module type
3008 def _GetModuleType(self
):
3009 return self
.Module
.ModuleType
3011 ## Return the component type (for Edk.x style of module)
3012 def _GetComponentType(self
):
3013 return self
.Module
.ComponentType
3015 ## Return the build type
3016 def _GetBuildType(self
):
3017 return self
.Module
.BuildType
3019 ## Return the PCD_IS_DRIVER setting
3020 def _GetPcdIsDriver(self
):
3021 return self
.Module
.PcdIsDriver
3023 ## Return the autogen version, i.e. module meta-file version
3024 def _GetAutoGenVersion(self
):
3025 return self
.Module
.AutoGenVersion
3027 ## Check if the module is library or not
3028 def _IsLibrary(self
):
3029 if self
._LibraryFlag
is None:
3030 if self
.Module
.LibraryClass
is not None and self
.Module
.LibraryClass
!= []:
3031 self
._LibraryFlag
= True
3033 self
._LibraryFlag
= False
3034 return self
._LibraryFlag
3036 ## Check if the module is binary module or not
3037 def _IsBinaryModule(self
):
3038 return self
.Module
.IsBinaryModule
3040 ## Return the directory to store intermediate files of the module
3041 def _GetBuildDir(self
):
3042 if self
._BuildDir
is None:
3043 self
._BuildDir
= path
.join(
3044 self
.PlatformInfo
.BuildDir
,
3047 self
.MetaFile
.BaseName
3049 CreateDirectory(self
._BuildDir
)
3050 return self
._BuildDir
3052 ## Return the directory to store the intermediate object files of the mdoule
3053 def _GetOutputDir(self
):
3054 if self
._OutputDir
is None:
3055 self
._OutputDir
= path
.join(self
.BuildDir
, "OUTPUT")
3056 CreateDirectory(self
._OutputDir
)
3057 return self
._OutputDir
3059 ## Return the directory to store ffs file
3060 def _GetFfsOutputDir(self
):
3061 if self
._FfsOutputDir
is None:
3062 if GlobalData
.gFdfParser
is not None:
3063 self
._FfsOutputDir
= path
.join(self
.PlatformInfo
.BuildDir
, "FV", "Ffs", self
.Guid
+ self
.Name
)
3065 self
._FfsOutputDir
= ''
3066 return self
._FfsOutputDir
3068 ## Return the directory to store auto-gened source files of the mdoule
3069 def _GetDebugDir(self
):
3070 if self
._DebugDir
is None:
3071 self
._DebugDir
= path
.join(self
.BuildDir
, "DEBUG")
3072 CreateDirectory(self
._DebugDir
)
3073 return self
._DebugDir
3075 ## Return the path of custom file
3076 def _GetCustomMakefile(self
):
3077 if self
._CustomMakefile
is None:
3078 self
._CustomMakefile
= {}
3079 for Type
in self
.Module
.CustomMakefile
:
3080 if Type
in gMakeTypeMap
:
3081 MakeType
= gMakeTypeMap
[Type
]
3084 if self
.SourceOverrideDir
is not None:
3085 File
= os
.path
.join(self
.SourceOverrideDir
, self
.Module
.CustomMakefile
[Type
])
3086 if not os
.path
.exists(File
):
3087 File
= os
.path
.join(self
.SourceDir
, self
.Module
.CustomMakefile
[Type
])
3089 File
= os
.path
.join(self
.SourceDir
, self
.Module
.CustomMakefile
[Type
])
3090 self
._CustomMakefile
[MakeType
] = File
3091 return self
._CustomMakefile
3093 ## Return the directory of the makefile
3095 # @retval string The directory string of module's makefile
3097 def _GetMakeFileDir(self
):
3098 return self
.BuildDir
3100 ## Return build command string
3102 # @retval string Build command string
3104 def _GetBuildCommand(self
):
3105 return self
.PlatformInfo
.BuildCommand
3107 ## Get object list of all packages the module and its dependent libraries belong to
3109 # @retval list The list of package object
3111 def _GetDerivedPackageList(self
):
3113 for M
in [self
.Module
] + self
.DependentLibraryList
:
3114 for Package
in M
.Packages
:
3115 if Package
in PackageList
:
3117 PackageList
.append(Package
)
3120 ## Get the depex string
3122 # @return : a string contain all depex expresion.
3123 def _GetDepexExpresionString(self
):
3126 ## DPX_SOURCE IN Define section.
3127 if self
.Module
.DxsFile
:
3129 for M
in [self
.Module
] + self
.DependentLibraryList
:
3130 Filename
= M
.MetaFile
.Path
3131 InfObj
= InfSectionParser
.InfSectionParser(Filename
)
3132 DepexExpresionList
= InfObj
.GetDepexExpresionList()
3133 for DepexExpresion
in DepexExpresionList
:
3134 for key
in DepexExpresion
.keys():
3135 Arch
, ModuleType
= key
3136 DepexExpr
= [x
for x
in DepexExpresion
[key
] if not str(x
).startswith('#')]
3137 # the type of build module is USER_DEFINED.
3138 # All different DEPEX section tags would be copied into the As Built INF file
3139 # and there would be separate DEPEX section tags
3140 if self
.ModuleType
.upper() == SUP_MODULE_USER_DEFINED
:
3141 if (Arch
.upper() == self
.Arch
.upper()) and (ModuleType
.upper() != TAB_ARCH_COMMON
):
3142 DepexList
.append({(Arch
, ModuleType
): DepexExpr
})
3144 if Arch
.upper() == TAB_ARCH_COMMON
or \
3145 (Arch
.upper() == self
.Arch
.upper() and \
3146 ModuleType
.upper() in [TAB_ARCH_COMMON
, self
.ModuleType
.upper()]):
3147 DepexList
.append({(Arch
, ModuleType
): DepexExpr
})
3149 #the type of build module is USER_DEFINED.
3150 if self
.ModuleType
.upper() == SUP_MODULE_USER_DEFINED
:
3151 for Depex
in DepexList
:
3152 for key
in Depex
.keys():
3153 DepexStr
+= '[Depex.%s.%s]\n' % key
3154 DepexStr
+= '\n'.join(['# '+ val
for val
in Depex
[key
]])
3157 return '[Depex.%s]\n' % self
.Arch
3160 #the type of build module not is USER_DEFINED.
3162 for Depex
in DepexList
:
3167 for D
in Depex
.values():
3168 DepexStr
+= ' '.join([val
for val
in D
])
3169 Index
= DepexStr
.find('END')
3170 if Index
> -1 and Index
== len(DepexStr
) - 3:
3171 DepexStr
= DepexStr
[:-3]
3172 DepexStr
= DepexStr
.strip()
3175 DepexStr
= DepexStr
.lstrip('(').rstrip(')').strip()
3177 return '[Depex.%s]\n' % self
.Arch
3178 return '[Depex.%s]\n# ' % self
.Arch
+ DepexStr
3180 ## Merge dependency expression
3182 # @retval list The token list of the dependency expression after parsed
3184 def _GetDepexTokenList(self
):
3185 if self
._DepexList
is None:
3186 self
._DepexList
= {}
3187 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
3188 return self
._DepexList
3190 self
._DepexList
[self
.ModuleType
] = []
3192 for ModuleType
in self
._DepexList
:
3193 DepexList
= self
._DepexList
[ModuleType
]
3195 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
3197 for M
in [self
.Module
] + self
.DependentLibraryList
:
3199 for D
in M
.Depex
[self
.Arch
, ModuleType
]:
3201 DepexList
.append('AND')
3202 DepexList
.append('(')
3204 if DepexList
[-1] == 'END': # no need of a END at this time
3206 DepexList
.append(')')
3209 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexList
))
3210 if 'BEFORE' in DepexList
or 'AFTER' in DepexList
:
3212 if len(DepexList
) > 0:
3213 EdkLogger
.verbose('')
3214 return self
._DepexList
3216 ## Merge dependency expression
3218 # @retval list The token list of the dependency expression after parsed
3220 def _GetDepexExpressionTokenList(self
):
3221 if self
._DepexExpressionList
is None:
3222 self
._DepexExpressionList
= {}
3223 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
3224 return self
._DepexExpressionList
3226 self
._DepexExpressionList
[self
.ModuleType
] = ''
3228 for ModuleType
in self
._DepexExpressionList
:
3229 DepexExpressionList
= self
._DepexExpressionList
[ModuleType
]
3231 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
3233 for M
in [self
.Module
] + self
.DependentLibraryList
:
3235 for D
in M
.DepexExpression
[self
.Arch
, ModuleType
]:
3236 if DepexExpressionList
!= '':
3237 DepexExpressionList
+= ' AND '
3238 DepexExpressionList
+= '('
3239 DepexExpressionList
+= D
3240 DepexExpressionList
= DepexExpressionList
.rstrip('END').strip()
3241 DepexExpressionList
+= ')'
3244 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexExpressionList
))
3245 if 'BEFORE' in DepexExpressionList
or 'AFTER' in DepexExpressionList
:
3247 if len(DepexExpressionList
) > 0:
3248 EdkLogger
.verbose('')
3249 self
._DepexExpressionList
[ModuleType
] = DepexExpressionList
3250 return self
._DepexExpressionList
3252 # Get the tiano core user extension, it is contain dependent library.
3253 # @retval: a list contain tiano core userextension.
3255 def _GetTianoCoreUserExtensionList(self
):
3256 TianoCoreUserExtentionList
= []
3257 for M
in [self
.Module
] + self
.DependentLibraryList
:
3258 Filename
= M
.MetaFile
.Path
3259 InfObj
= InfSectionParser
.InfSectionParser(Filename
)
3260 TianoCoreUserExtenList
= InfObj
.GetUserExtensionTianoCore()
3261 for TianoCoreUserExtent
in TianoCoreUserExtenList
:
3262 for Section
in TianoCoreUserExtent
.keys():
3263 ItemList
= Section
.split(TAB_SPLIT
)
3265 if len(ItemList
) == 4:
3267 if Arch
.upper() == TAB_ARCH_COMMON
or Arch
.upper() == self
.Arch
.upper():
3269 TianoCoreList
.extend([TAB_SECTION_START
+ Section
+ TAB_SECTION_END
])
3270 TianoCoreList
.extend(TianoCoreUserExtent
[Section
][:])
3271 TianoCoreList
.append('\n')
3272 TianoCoreUserExtentionList
.append(TianoCoreList
)
3274 return TianoCoreUserExtentionList
3276 ## Return the list of specification version required for the module
3278 # @retval list The list of specification defined in module file
3280 def _GetSpecification(self
):
3281 return self
.Module
.Specification
3283 ## Tool option for the module build
3285 # @param PlatformInfo The object of PlatformBuildInfo
3286 # @retval dict The dict containing valid options
3288 def _GetModuleBuildOption(self
):
3289 if self
._BuildOption
is None:
3290 self
._BuildOption
, self
.BuildRuleOrder
= self
.PlatformInfo
.ApplyBuildOption(self
.Module
)
3291 if self
.BuildRuleOrder
:
3292 self
.BuildRuleOrder
= ['.%s' % Ext
for Ext
in self
.BuildRuleOrder
.split()]
3293 return self
._BuildOption
3295 ## Get include path list from tool option for the module build
3297 # @retval list The include path list
3299 def _GetBuildOptionIncPathList(self
):
3300 if self
._BuildOptionIncPathList
is None:
3302 # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
3303 # is the former use /I , the Latter used -I to specify include directories
3305 if self
.PlatformInfo
.ToolChainFamily
in ('MSFT'):
3306 BuildOptIncludeRegEx
= gBuildOptIncludePatternMsft
3307 elif self
.PlatformInfo
.ToolChainFamily
in ('INTEL', 'GCC', 'RVCT'):
3308 BuildOptIncludeRegEx
= gBuildOptIncludePatternOther
3311 # New ToolChainFamily, don't known whether there is option to specify include directories
3313 self
._BuildOptionIncPathList
= []
3314 return self
._BuildOptionIncPathList
3316 BuildOptionIncPathList
= []
3317 for Tool
in ('CC', 'PP', 'VFRPP', 'ASLPP', 'ASLCC', 'APP', 'ASM'):
3320 FlagOption
= self
.BuildOption
[Tool
][Attr
]
3324 if self
.PlatformInfo
.ToolChainFamily
!= 'RVCT':
3325 IncPathList
= [NormPath(Path
, self
.Macros
) for Path
in BuildOptIncludeRegEx
.findall(FlagOption
)]
3328 # RVCT may specify a list of directory seperated by commas
3331 for Path
in BuildOptIncludeRegEx
.findall(FlagOption
):
3332 PathList
= GetSplitList(Path
, TAB_COMMA_SPLIT
)
3333 IncPathList
+= [NormPath(PathEntry
, self
.Macros
) for PathEntry
in PathList
]
3336 # EDK II modules must not reference header files outside of the packages they depend on or
3337 # within the module's directory tree. Report error if violation.
3339 if self
.AutoGenVersion
>= 0x00010005 and len(IncPathList
) > 0:
3340 for Path
in IncPathList
:
3341 if (Path
not in self
.IncludePathList
) and (CommonPath([Path
, self
.MetaFile
.Dir
]) != self
.MetaFile
.Dir
):
3342 ErrMsg
= "The include directory for the EDK II module in this line is invalid %s specified in %s FLAGS '%s'" % (Path
, Tool
, FlagOption
)
3343 EdkLogger
.error("build",
3346 File
=str(self
.MetaFile
))
3349 BuildOptionIncPathList
+= IncPathList
3351 self
._BuildOptionIncPathList
= BuildOptionIncPathList
3353 return self
._BuildOptionIncPathList
3355 ## Return a list of files which can be built from source
3357 # What kind of files can be built is determined by build rules in
3358 # $(CONF_DIRECTORY)/build_rule.txt and toolchain family.
3360 def _GetSourceFileList(self
):
3361 if self
._SourceFileList
is None:
3362 self
._SourceFileList
= []
3363 for F
in self
.Module
.Sources
:
3365 if F
.TagName
not in ("", "*", self
.ToolChain
):
3366 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "The toolchain [%s] for processing file [%s] is found, "
3367 "but [%s] is needed" % (F
.TagName
, str(F
), self
.ToolChain
))
3369 # match tool chain family or build rule family
3370 if F
.ToolChainFamily
not in ("", "*", self
.ToolChainFamily
, self
.BuildRuleFamily
):
3373 "The file [%s] must be built by tools of [%s], " \
3374 "but current toolchain family is [%s], buildrule family is [%s]" \
3375 % (str(F
), F
.ToolChainFamily
, self
.ToolChainFamily
, self
.BuildRuleFamily
))
3378 # add the file path into search path list for file including
3379 if F
.Dir
not in self
.IncludePathList
and self
.AutoGenVersion
>= 0x00010005:
3380 self
.IncludePathList
.insert(0, F
.Dir
)
3381 self
._SourceFileList
.append(F
)
3383 self
._MatchBuildRuleOrder
(self
._SourceFileList
)
3385 for F
in self
._SourceFileList
:
3386 self
._ApplyBuildRule
(F
, TAB_UNKNOWN_FILE
)
3387 return self
._SourceFileList
3389 def _MatchBuildRuleOrder(self
, FileList
):
3391 self
._GetModuleBuildOption
()
3392 for SingleFile
in FileList
:
3393 if self
.BuildRuleOrder
and SingleFile
.Ext
in self
.BuildRuleOrder
and SingleFile
.Ext
in self
.BuildRules
:
3394 key
= SingleFile
.Path
.split(SingleFile
.Ext
)[0]
3395 if key
in Order_Dict
:
3396 Order_Dict
[key
].append(SingleFile
.Ext
)
3398 Order_Dict
[key
] = [SingleFile
.Ext
]
3401 for F
in Order_Dict
:
3402 if len(Order_Dict
[F
]) > 1:
3403 Order_Dict
[F
].sort(key
=lambda i
: self
.BuildRuleOrder
.index(i
))
3404 for Ext
in Order_Dict
[F
][1:]:
3405 RemoveList
.append(F
+ Ext
)
3407 for item
in RemoveList
:
3408 FileList
.remove(item
)
3412 ## Return the list of unicode files
3413 def _GetUnicodeFileList(self
):
3414 if self
._UnicodeFileList
is None:
3415 if TAB_UNICODE_FILE
in self
.FileTypes
:
3416 self
._UnicodeFileList
= self
.FileTypes
[TAB_UNICODE_FILE
]
3418 self
._UnicodeFileList
= []
3419 return self
._UnicodeFileList
3421 ## Return the list of vfr files
3422 def _GetVfrFileList(self
):
3423 if self
._VfrFileList
is None:
3424 if TAB_VFR_FILE
in self
.FileTypes
:
3425 self
._VfrFileList
= self
.FileTypes
[TAB_VFR_FILE
]
3427 self
._VfrFileList
= []
3428 return self
._VfrFileList
3430 ## Return the list of Image Definition files
3431 def _GetIdfFileList(self
):
3432 if self
._IdfFileList
is None:
3433 if TAB_IMAGE_FILE
in self
.FileTypes
:
3434 self
._IdfFileList
= self
.FileTypes
[TAB_IMAGE_FILE
]
3436 self
._IdfFileList
= []
3437 return self
._IdfFileList
3439 ## Return a list of files which can be built from binary
3441 # "Build" binary files are just to copy them to build directory.
3443 # @retval list The list of files which can be built later
3445 def _GetBinaryFiles(self
):
3446 if self
._BinaryFileList
is None:
3447 self
._BinaryFileList
= []
3448 for F
in self
.Module
.Binaries
:
3449 if F
.Target
not in ['COMMON', '*'] and F
.Target
!= self
.BuildTarget
:
3451 self
._BinaryFileList
.append(F
)
3452 self
._ApplyBuildRule
(F
, F
.Type
)
3453 return self
._BinaryFileList
3455 def _GetBuildRules(self
):
3456 if self
._BuildRules
is None:
3458 BuildRuleDatabase
= self
.PlatformInfo
.BuildRule
3459 for Type
in BuildRuleDatabase
.FileTypeList
:
3460 #first try getting build rule by BuildRuleFamily
3461 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.BuildRuleFamily
]
3463 # build type is always module type, but ...
3464 if self
.ModuleType
!= self
.BuildType
:
3465 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.BuildRuleFamily
]
3466 #second try getting build rule by ToolChainFamily
3468 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.ToolChainFamily
]
3470 # build type is always module type, but ...
3471 if self
.ModuleType
!= self
.BuildType
:
3472 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.ToolChainFamily
]
3475 RuleObject
= RuleObject
.Instantiate(self
.Macros
)
3476 BuildRules
[Type
] = RuleObject
3477 for Ext
in RuleObject
.SourceFileExtList
:
3478 BuildRules
[Ext
] = RuleObject
3479 self
._BuildRules
= BuildRules
3480 return self
._BuildRules
3482 def _ApplyBuildRule(self
, File
, FileType
):
3483 if self
._BuildTargets
is None:
3484 self
._IntroBuildTargetList
= set()
3485 self
._FinalBuildTargetList
= set()
3486 self
._BuildTargets
= {}
3487 self
._FileTypes
= {}
3489 SubDirectory
= os
.path
.join(self
.OutputDir
, File
.SubDir
)
3490 if not os
.path
.exists(SubDirectory
):
3491 CreateDirectory(SubDirectory
)
3497 # Make sure to get build rule order value
3499 self
._GetModuleBuildOption
()
3501 while Index
< len(SourceList
):
3502 Source
= SourceList
[Index
]
3506 CreateDirectory(Source
.Dir
)
3508 if File
.IsBinary
and File
== Source
and self
._BinaryFileList
is not None and File
in self
._BinaryFileList
:
3509 # Skip all files that are not binary libraries
3510 if not self
.IsLibrary
:
3512 RuleObject
= self
.BuildRules
[TAB_DEFAULT_BINARY_FILE
]
3513 elif FileType
in self
.BuildRules
:
3514 RuleObject
= self
.BuildRules
[FileType
]
3515 elif Source
.Ext
in self
.BuildRules
:
3516 RuleObject
= self
.BuildRules
[Source
.Ext
]
3518 # stop at no more rules
3520 self
._FinalBuildTargetList
.add(LastTarget
)
3523 FileType
= RuleObject
.SourceFileType
3524 if FileType
not in self
._FileTypes
:
3525 self
._FileTypes
[FileType
] = set()
3526 self
._FileTypes
[FileType
].add(Source
)
3528 # stop at STATIC_LIBRARY for library
3529 if self
.IsLibrary
and FileType
== TAB_STATIC_LIBRARY
:
3531 self
._FinalBuildTargetList
.add(LastTarget
)
3534 Target
= RuleObject
.Apply(Source
, self
.BuildRuleOrder
)
3537 self
._FinalBuildTargetList
.add(LastTarget
)
3539 elif not Target
.Outputs
:
3540 # Only do build for target with outputs
3541 self
._FinalBuildTargetList
.add(Target
)
3543 if FileType
not in self
._BuildTargets
:
3544 self
._BuildTargets
[FileType
] = set()
3545 self
._BuildTargets
[FileType
].add(Target
)
3547 if not Source
.IsBinary
and Source
== File
:
3548 self
._IntroBuildTargetList
.add(Target
)
3550 # to avoid cyclic rule
3551 if FileType
in RuleChain
:
3554 RuleChain
.append(FileType
)
3555 SourceList
.extend(Target
.Outputs
)
3557 FileType
= TAB_UNKNOWN_FILE
3559 def _GetTargets(self
):
3560 if self
._BuildTargets
is None:
3561 self
._IntroBuildTargetList
= set()
3562 self
._FinalBuildTargetList
= set()
3563 self
._BuildTargets
= {}
3564 self
._FileTypes
= {}
3566 #TRICK: call _GetSourceFileList to apply build rule for source files
3567 if self
.SourceFileList
:
3570 #TRICK: call _GetBinaryFileList to apply build rule for binary files
3571 if self
.BinaryFileList
:
3574 return self
._BuildTargets
3576 def _GetIntroTargetList(self
):
3578 return self
._IntroBuildTargetList
3580 def _GetFinalTargetList(self
):
3582 return self
._FinalBuildTargetList
3584 def _GetFileTypes(self
):
3586 return self
._FileTypes
3588 ## Get the list of package object the module depends on
3590 # @retval list The package object list
3592 def _GetDependentPackageList(self
):
3593 return self
.Module
.Packages
3595 ## Return the list of auto-generated code file
3597 # @retval list The list of auto-generated file
3599 def _GetAutoGenFileList(self
):
3600 UniStringAutoGenC
= True
3601 IdfStringAutoGenC
= True
3602 UniStringBinBuffer
= StringIO()
3603 IdfGenBinBuffer
= StringIO()
3604 if self
.BuildType
== 'UEFI_HII':
3605 UniStringAutoGenC
= False
3606 IdfStringAutoGenC
= False
3607 if self
._AutoGenFileList
is None:
3608 self
._AutoGenFileList
= {}
3609 AutoGenC
= TemplateString()
3610 AutoGenH
= TemplateString()
3611 StringH
= TemplateString()
3612 StringIdf
= TemplateString()
3613 GenC
.CreateCode(self
, AutoGenC
, AutoGenH
, StringH
, UniStringAutoGenC
, UniStringBinBuffer
, StringIdf
, IdfStringAutoGenC
, IdfGenBinBuffer
)
3615 # AutoGen.c is generated if there are library classes in inf, or there are object files
3617 if str(AutoGenC
) != "" and (len(self
.Module
.LibraryClasses
) > 0
3618 or TAB_OBJECT_FILE
in self
.FileTypes
):
3619 AutoFile
= PathClass(gAutoGenCodeFileName
, self
.DebugDir
)
3620 self
._AutoGenFileList
[AutoFile
] = str(AutoGenC
)
3621 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3622 if str(AutoGenH
) != "":
3623 AutoFile
= PathClass(gAutoGenHeaderFileName
, self
.DebugDir
)
3624 self
._AutoGenFileList
[AutoFile
] = str(AutoGenH
)
3625 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3626 if str(StringH
) != "":
3627 AutoFile
= PathClass(gAutoGenStringFileName
% {"module_name":self
.Name
}, self
.DebugDir
)
3628 self
._AutoGenFileList
[AutoFile
] = str(StringH
)
3629 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3630 if UniStringBinBuffer
is not None and UniStringBinBuffer
.getvalue() != "":
3631 AutoFile
= PathClass(gAutoGenStringFormFileName
% {"module_name":self
.Name
}, self
.OutputDir
)
3632 self
._AutoGenFileList
[AutoFile
] = UniStringBinBuffer
.getvalue()
3633 AutoFile
.IsBinary
= True
3634 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3635 if UniStringBinBuffer
is not None:
3636 UniStringBinBuffer
.close()
3637 if str(StringIdf
) != "":
3638 AutoFile
= PathClass(gAutoGenImageDefFileName
% {"module_name":self
.Name
}, self
.DebugDir
)
3639 self
._AutoGenFileList
[AutoFile
] = str(StringIdf
)
3640 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3641 if IdfGenBinBuffer
is not None and IdfGenBinBuffer
.getvalue() != "":
3642 AutoFile
= PathClass(gAutoGenIdfFileName
% {"module_name":self
.Name
}, self
.OutputDir
)
3643 self
._AutoGenFileList
[AutoFile
] = IdfGenBinBuffer
.getvalue()
3644 AutoFile
.IsBinary
= True
3645 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3646 if IdfGenBinBuffer
is not None:
3647 IdfGenBinBuffer
.close()
3648 return self
._AutoGenFileList
3650 ## Return the list of library modules explicitly or implicityly used by this module
3651 def _GetLibraryList(self
):
3652 if self
._DependentLibraryList
is None:
3653 # only merge library classes and PCD for non-library module
3655 self
._DependentLibraryList
= []
3657 if self
.AutoGenVersion
< 0x00010005:
3658 self
._DependentLibraryList
= self
.PlatformInfo
.ResolveLibraryReference(self
.Module
)
3660 self
._DependentLibraryList
= self
.PlatformInfo
.ApplyLibraryInstance(self
.Module
)
3661 return self
._DependentLibraryList
3664 def UpdateComments(Recver
, Src
):
3666 if Key
not in Recver
:
3668 Recver
[Key
].extend(Src
[Key
])
3669 ## Get the list of PCDs from current module
3671 # @retval list The list of PCD
3673 def _GetModulePcdList(self
):
3674 if self
._ModulePcdList
is None:
3675 # apply PCD settings from platform
3676 self
._ModulePcdList
= self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, self
.Module
.Pcds
)
3677 self
.UpdateComments(self
._PcdComments
, self
.Module
.PcdComments
)
3678 return self
._ModulePcdList
3680 ## Get the list of PCDs from dependent libraries
3682 # @retval list The list of PCD
3684 def _GetLibraryPcdList(self
):
3685 if self
._LibraryPcdList
is None:
3686 Pcds
= OrderedDict()
3687 if not self
.IsLibrary
:
3688 # get PCDs from dependent libraries
3689 for Library
in self
.DependentLibraryList
:
3690 self
.UpdateComments(self
._PcdComments
, Library
.PcdComments
)
3691 for Key
in Library
.Pcds
:
3692 # skip duplicated PCDs
3693 if Key
in self
.Module
.Pcds
or Key
in Pcds
:
3695 Pcds
[Key
] = copy
.copy(Library
.Pcds
[Key
])
3696 # apply PCD settings from platform
3697 self
._LibraryPcdList
= self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, Pcds
)
3699 self
._LibraryPcdList
= []
3700 return self
._LibraryPcdList
3702 ## Get the GUID value mapping
3704 # @retval dict The mapping between GUID cname and its value
3706 def _GetGuidList(self
):
3707 if self
._GuidList
is None:
3708 self
._GuidList
= OrderedDict()
3709 self
._GuidList
.update(self
.Module
.Guids
)
3710 for Library
in self
.DependentLibraryList
:
3711 self
._GuidList
.update(Library
.Guids
)
3712 self
.UpdateComments(self
._GuidComments
, Library
.GuidComments
)
3713 self
.UpdateComments(self
._GuidComments
, self
.Module
.GuidComments
)
3714 return self
._GuidList
3716 def GetGuidsUsedByPcd(self
):
3717 if self
._GuidsUsedByPcd
is None:
3718 self
._GuidsUsedByPcd
= OrderedDict()
3719 self
._GuidsUsedByPcd
.update(self
.Module
.GetGuidsUsedByPcd())
3720 for Library
in self
.DependentLibraryList
:
3721 self
._GuidsUsedByPcd
.update(Library
.GetGuidsUsedByPcd())
3722 return self
._GuidsUsedByPcd
3723 ## Get the protocol value mapping
3725 # @retval dict The mapping between protocol cname and its value
3727 def _GetProtocolList(self
):
3728 if self
._ProtocolList
is None:
3729 self
._ProtocolList
= OrderedDict()
3730 self
._ProtocolList
.update(self
.Module
.Protocols
)
3731 for Library
in self
.DependentLibraryList
:
3732 self
._ProtocolList
.update(Library
.Protocols
)
3733 self
.UpdateComments(self
._ProtocolComments
, Library
.ProtocolComments
)
3734 self
.UpdateComments(self
._ProtocolComments
, self
.Module
.ProtocolComments
)
3735 return self
._ProtocolList
3737 ## Get the PPI value mapping
3739 # @retval dict The mapping between PPI cname and its value
3741 def _GetPpiList(self
):
3742 if self
._PpiList
is None:
3743 self
._PpiList
= OrderedDict()
3744 self
._PpiList
.update(self
.Module
.Ppis
)
3745 for Library
in self
.DependentLibraryList
:
3746 self
._PpiList
.update(Library
.Ppis
)
3747 self
.UpdateComments(self
._PpiComments
, Library
.PpiComments
)
3748 self
.UpdateComments(self
._PpiComments
, self
.Module
.PpiComments
)
3749 return self
._PpiList
3751 ## Get the list of include search path
3753 # @retval list The list path
3755 def _GetIncludePathList(self
):
3756 if self
._IncludePathList
is None:
3757 self
._IncludePathList
= []
3758 if self
.AutoGenVersion
< 0x00010005:
3759 for Inc
in self
.Module
.Includes
:
3760 if Inc
not in self
._IncludePathList
:
3761 self
._IncludePathList
.append(Inc
)
3763 Inc
= path
.join(Inc
, self
.Arch
.capitalize())
3764 if os
.path
.exists(Inc
) and Inc
not in self
._IncludePathList
:
3765 self
._IncludePathList
.append(Inc
)
3766 # Edk module needs to put DEBUG_DIR at the end of search path and not to use SOURCE_DIR all the time
3767 self
._IncludePathList
.append(self
.DebugDir
)
3769 self
._IncludePathList
.append(self
.MetaFile
.Dir
)
3770 self
._IncludePathList
.append(self
.DebugDir
)
3772 for Package
in self
.Module
.Packages
:
3773 PackageDir
= mws
.join(self
.WorkspaceDir
, Package
.MetaFile
.Dir
)
3774 if PackageDir
not in self
._IncludePathList
:
3775 self
._IncludePathList
.append(PackageDir
)
3776 IncludesList
= Package
.Includes
3777 if Package
._PrivateIncludes
:
3778 if not self
.MetaFile
.Path
.startswith(PackageDir
):
3779 IncludesList
= list(set(Package
.Includes
).difference(set(Package
._PrivateIncludes
)))
3780 for Inc
in IncludesList
:
3781 if Inc
not in self
._IncludePathList
:
3782 self
._IncludePathList
.append(str(Inc
))
3783 return self
._IncludePathList
3785 def _GetIncludePathLength(self
):
3786 self
._IncludePathLength
= 0
3787 if self
._IncludePathList
:
3788 for inc
in self
._IncludePathList
:
3789 self
._IncludePathLength
+= len(' ' + inc
)
3790 return self
._IncludePathLength
3792 ## Get HII EX PCDs which maybe used by VFR
3794 # efivarstore used by VFR may relate with HII EX PCDs
3795 # Get the variable name and GUID from efivarstore and HII EX PCD
3796 # List the HII EX PCDs in As Built INF if both name and GUID match.
3798 # @retval list HII EX PCDs
3800 def _GetPcdsMaybeUsedByVfr(self
):
3801 if not self
.SourceFileList
:
3805 for SrcFile
in self
.SourceFileList
:
3806 if SrcFile
.Ext
.lower() != '.vfr':
3808 Vfri
= os
.path
.join(self
.OutputDir
, SrcFile
.BaseName
+ '.i')
3809 if not os
.path
.exists(Vfri
):
3811 VfriFile
= open(Vfri
, 'r')
3812 Content
= VfriFile
.read()
3814 Pos
= Content
.find('efivarstore')
3817 # Make sure 'efivarstore' is the start of efivarstore statement
3818 # In case of the value of 'name' (name = efivarstore) is equal to 'efivarstore'
3821 while Index
>= 0 and Content
[Index
] in ' \t\r\n':
3823 if Index
>= 0 and Content
[Index
] != ';':
3824 Pos
= Content
.find('efivarstore', Pos
+ len('efivarstore'))
3827 # 'efivarstore' must be followed by name and guid
3829 Name
= gEfiVarStoreNamePattern
.search(Content
, Pos
)
3832 Guid
= gEfiVarStoreGuidPattern
.search(Content
, Pos
)
3835 NameArray
= ConvertStringToByteArray('L"' + Name
.group(1) + '"')
3836 NameGuids
.append((NameArray
, GuidStructureStringToGuidString(Guid
.group(1))))
3837 Pos
= Content
.find('efivarstore', Name
.end())
3841 for Pcd
in self
.PlatformInfo
.Platform
.Pcds
.values():
3842 if Pcd
.Type
!= TAB_PCDS_DYNAMIC_EX_HII
:
3844 for SkuName
in Pcd
.SkuInfoList
:
3845 SkuInfo
= Pcd
.SkuInfoList
[SkuName
]
3846 Name
= ConvertStringToByteArray(SkuInfo
.VariableName
)
3847 Value
= GuidValue(SkuInfo
.VariableGuid
, self
.PlatformInfo
.PackageList
, self
.MetaFile
.Path
)
3850 Guid
= GuidStructureStringToGuidString(Value
)
3851 if (Name
, Guid
) in NameGuids
and Pcd
not in HiiExPcds
:
3852 HiiExPcds
.append(Pcd
)
3857 def _GenOffsetBin(self
):
3859 for SourceFile
in self
.Module
.Sources
:
3860 if SourceFile
.Type
.upper() == ".VFR" :
3862 # search the .map file to find the offset of vfr binary in the PE32+/TE file.
3864 VfrUniBaseName
[SourceFile
.BaseName
] = (SourceFile
.BaseName
+ "Bin")
3865 if SourceFile
.Type
.upper() == ".UNI" :
3867 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
3869 VfrUniBaseName
["UniOffsetName"] = (self
.Name
+ "Strings")
3871 if len(VfrUniBaseName
) == 0:
3873 MapFileName
= os
.path
.join(self
.OutputDir
, self
.Name
+ ".map")
3874 EfiFileName
= os
.path
.join(self
.OutputDir
, self
.Name
+ ".efi")
3875 VfrUniOffsetList
= GetVariableOffset(MapFileName
, EfiFileName
, VfrUniBaseName
.values())
3876 if not VfrUniOffsetList
:
3879 OutputName
= '%sOffset.bin' % self
.Name
3880 UniVfrOffsetFileName
= os
.path
.join( self
.OutputDir
, OutputName
)
3883 fInputfile
= open(UniVfrOffsetFileName
, "wb+", 0)
3885 EdkLogger
.error("build", FILE_OPEN_FAILURE
, "File open failed for %s" % UniVfrOffsetFileName
,None)
3887 # Use a instance of StringIO to cache data
3888 fStringIO
= StringIO('')
3890 for Item
in VfrUniOffsetList
:
3891 if (Item
[0].find("Strings") != -1):
3893 # UNI offset in image.
3895 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }
3897 UniGuid
= [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66]
3898 UniGuid
= [chr(ItemGuid
) for ItemGuid
in UniGuid
]
3899 fStringIO
.write(''.join(UniGuid
))
3900 UniValue
= pack ('Q', int (Item
[1], 16))
3901 fStringIO
.write (UniValue
)
3904 # VFR binary offset in image.
3906 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };
3908 VfrGuid
= [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2]
3909 VfrGuid
= [chr(ItemGuid
) for ItemGuid
in VfrGuid
]
3910 fStringIO
.write(''.join(VfrGuid
))
3912 VfrValue
= pack ('Q', int (Item
[1], 16))
3913 fStringIO
.write (VfrValue
)
3915 # write data into file.
3918 fInputfile
.write (fStringIO
.getvalue())
3920 EdkLogger
.error("build", FILE_WRITE_FAILURE
, "Write data to file %s failed, please check whether the "
3921 "file been locked or using by other applications." %UniVfrOffsetFileName
,None)
3927 ## Create AsBuilt INF file the module
3929 def CreateAsBuiltInf(self
, IsOnlyCopy
= False):
3930 self
.OutputFile
= []
3932 if GlobalData
.gBinCacheDest
:
3933 self
.CopyModuleToCache()
3936 if self
.IsAsBuiltInfCreated
:
3939 # Skip the following code for EDK I inf
3940 if self
.AutoGenVersion
< 0x00010005:
3943 # Skip the following code for libraries
3947 # Skip the following code for modules with no source files
3948 if self
.SourceFileList
is None or self
.SourceFileList
== []:
3951 # Skip the following code for modules without any binary files
3952 if self
.BinaryFileList
<> None and self
.BinaryFileList
<> []:
3955 ### TODO: How to handles mixed source and binary modules
3957 # Find all DynamicEx and PatchableInModule PCDs used by this module and dependent libraries
3958 # Also find all packages that the DynamicEx PCDs depend on
3963 PcdTokenSpaceList
= []
3964 for Pcd
in self
.ModulePcdList
+ self
.LibraryPcdList
:
3965 if Pcd
.Type
== TAB_PCDS_PATCHABLE_IN_MODULE
:
3966 PatchablePcds
+= [Pcd
]
3967 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, 'PatchableInModule'))
3968 elif Pcd
.Type
in GenC
.gDynamicExPcd
:
3971 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, 'DynamicEx'))
3972 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, 'Dynamic'))
3973 PcdTokenSpaceList
.append(Pcd
.TokenSpaceGuidCName
)
3974 GuidList
= OrderedDict()
3975 GuidList
.update(self
.GuidList
)
3976 for TokenSpace
in self
.GetGuidsUsedByPcd():
3977 # If token space is not referred by patch PCD or Ex PCD, remove the GUID from GUID list
3978 # The GUIDs in GUIDs section should really be the GUIDs in source INF or referred by Ex an patch PCDs
3979 if TokenSpace
not in PcdTokenSpaceList
and TokenSpace
in GuidList
:
3980 GuidList
.pop(TokenSpace
)
3981 CheckList
= (GuidList
, self
.PpiList
, self
.ProtocolList
, PcdCheckList
)
3982 for Package
in self
.DerivedPackageList
:
3983 if Package
in Packages
:
3985 BeChecked
= (Package
.Guids
, Package
.Ppis
, Package
.Protocols
, Package
.Pcds
)
3987 for Index
in range(len(BeChecked
)):
3988 for Item
in CheckList
[Index
]:
3989 if Item
in BeChecked
[Index
]:
3990 Packages
+= [Package
]
3995 VfrPcds
= self
._GetPcdsMaybeUsedByVfr
()
3996 for Pkg
in self
.PlatformInfo
.PackageList
:
3999 for VfrPcd
in VfrPcds
:
4000 if ((VfrPcd
.TokenCName
, VfrPcd
.TokenSpaceGuidCName
, 'DynamicEx') in Pkg
.Pcds
or
4001 (VfrPcd
.TokenCName
, VfrPcd
.TokenSpaceGuidCName
, 'Dynamic') in Pkg
.Pcds
):
4005 ModuleType
= self
.ModuleType
4006 if ModuleType
== 'UEFI_DRIVER' and self
.DepexGenerated
:
4007 ModuleType
= 'DXE_DRIVER'
4010 if self
.PcdIsDriver
!= '':
4011 DriverType
= self
.PcdIsDriver
4014 MDefs
= self
.Module
.Defines
4017 'module_name' : self
.Name
,
4018 'module_guid' : Guid
,
4019 'module_module_type' : ModuleType
,
4020 'module_version_string' : [MDefs
['VERSION_STRING']] if 'VERSION_STRING' in MDefs
else [],
4021 'pcd_is_driver_string' : [],
4022 'module_uefi_specification_version' : [],
4023 'module_pi_specification_version' : [],
4024 'module_entry_point' : self
.Module
.ModuleEntryPointList
,
4025 'module_unload_image' : self
.Module
.ModuleUnloadImageList
,
4026 'module_constructor' : self
.Module
.ConstructorList
,
4027 'module_destructor' : self
.Module
.DestructorList
,
4028 'module_shadow' : [MDefs
['SHADOW']] if 'SHADOW' in MDefs
else [],
4029 'module_pci_vendor_id' : [MDefs
['PCI_VENDOR_ID']] if 'PCI_VENDOR_ID' in MDefs
else [],
4030 'module_pci_device_id' : [MDefs
['PCI_DEVICE_ID']] if 'PCI_DEVICE_ID' in MDefs
else [],
4031 'module_pci_class_code' : [MDefs
['PCI_CLASS_CODE']] if 'PCI_CLASS_CODE' in MDefs
else [],
4032 'module_pci_revision' : [MDefs
['PCI_REVISION']] if 'PCI_REVISION' in MDefs
else [],
4033 'module_build_number' : [MDefs
['BUILD_NUMBER']] if 'BUILD_NUMBER' in MDefs
else [],
4034 'module_spec' : [MDefs
['SPEC']] if 'SPEC' in MDefs
else [],
4035 'module_uefi_hii_resource_section' : [MDefs
['UEFI_HII_RESOURCE_SECTION']] if 'UEFI_HII_RESOURCE_SECTION' in MDefs
else [],
4036 'module_uni_file' : [MDefs
['MODULE_UNI_FILE']] if 'MODULE_UNI_FILE' in MDefs
else [],
4037 'module_arch' : self
.Arch
,
4038 'package_item' : ['%s' % (Package
.MetaFile
.File
.replace('\\', '/')) for Package
in Packages
],
4040 'patchablepcd_item' : [],
4042 'protocol_item' : [],
4046 'libraryclasses_item' : []
4049 if 'MODULE_UNI_FILE' in MDefs
:
4050 UNIFile
= os
.path
.join(self
.MetaFile
.Dir
, MDefs
['MODULE_UNI_FILE'])
4051 if os
.path
.isfile(UNIFile
):
4052 shutil
.copy2(UNIFile
, self
.OutputDir
)
4054 if self
.AutoGenVersion
> int(gInfSpecVersion
, 0):
4055 AsBuiltInfDict
['module_inf_version'] = '0x%08x' % self
.AutoGenVersion
4057 AsBuiltInfDict
['module_inf_version'] = gInfSpecVersion
4060 AsBuiltInfDict
['pcd_is_driver_string'] += [DriverType
]
4062 if 'UEFI_SPECIFICATION_VERSION' in self
.Specification
:
4063 AsBuiltInfDict
['module_uefi_specification_version'] += [self
.Specification
['UEFI_SPECIFICATION_VERSION']]
4064 if 'PI_SPECIFICATION_VERSION' in self
.Specification
:
4065 AsBuiltInfDict
['module_pi_specification_version'] += [self
.Specification
['PI_SPECIFICATION_VERSION']]
4067 OutputDir
= self
.OutputDir
.replace('\\', '/').strip('/')
4068 DebugDir
= self
.DebugDir
.replace('\\', '/').strip('/')
4069 for Item
in self
.CodaTargetList
:
4070 File
= Item
.Target
.Path
.replace('\\', '/').strip('/').replace(DebugDir
, '').replace(OutputDir
, '').strip('/')
4071 if File
not in self
.OutputFile
:
4072 self
.OutputFile
.append(File
)
4073 if os
.path
.isabs(File
):
4074 File
= File
.replace('\\', '/').strip('/').replace(OutputDir
, '').strip('/')
4075 if Item
.Target
.Ext
.lower() == '.aml':
4076 AsBuiltInfDict
['binary_item'] += ['ASL|' + File
]
4077 elif Item
.Target
.Ext
.lower() == '.acpi':
4078 AsBuiltInfDict
['binary_item'] += ['ACPI|' + File
]
4079 elif Item
.Target
.Ext
.lower() == '.efi':
4080 AsBuiltInfDict
['binary_item'] += ['PE32|' + self
.Name
+ '.efi']
4082 AsBuiltInfDict
['binary_item'] += ['BIN|' + File
]
4083 if self
.DepexGenerated
:
4084 if self
.Name
+ '.depex' not in self
.OutputFile
:
4085 self
.OutputFile
.append(self
.Name
+ '.depex')
4086 if self
.ModuleType
in ['PEIM']:
4087 AsBuiltInfDict
['binary_item'] += ['PEI_DEPEX|' + self
.Name
+ '.depex']
4088 if self
.ModuleType
in ['DXE_DRIVER', 'DXE_RUNTIME_DRIVER', 'DXE_SAL_DRIVER', 'UEFI_DRIVER']:
4089 AsBuiltInfDict
['binary_item'] += ['DXE_DEPEX|' + self
.Name
+ '.depex']
4090 if self
.ModuleType
in ['DXE_SMM_DRIVER']:
4091 AsBuiltInfDict
['binary_item'] += ['SMM_DEPEX|' + self
.Name
+ '.depex']
4093 Bin
= self
._GenOffsetBin
()
4095 AsBuiltInfDict
['binary_item'] += ['BIN|%s' % Bin
]
4096 if Bin
not in self
.OutputFile
:
4097 self
.OutputFile
.append(Bin
)
4099 for Root
, Dirs
, Files
in os
.walk(OutputDir
):
4101 if File
.lower().endswith('.pdb'):
4102 AsBuiltInfDict
['binary_item'] += ['DISPOSABLE|' + File
]
4103 if File
not in self
.OutputFile
:
4104 self
.OutputFile
.append(File
)
4105 HeaderComments
= self
.Module
.HeaderComments
4107 for Index
in range(len(HeaderComments
)):
4108 if HeaderComments
[Index
].find('@BinaryHeader') != -1:
4109 HeaderComments
[Index
] = HeaderComments
[Index
].replace('@BinaryHeader', '@file')
4112 AsBuiltInfDict
['header_comments'] = '\n'.join(HeaderComments
[StartPos
:]).replace(':#', '://')
4113 AsBuiltInfDict
['tail_comments'] = '\n'.join(self
.Module
.TailComments
)
4116 (self
.ProtocolList
, self
._ProtocolComments
, 'protocol_item'),
4117 (self
.PpiList
, self
._PpiComments
, 'ppi_item'),
4118 (GuidList
, self
._GuidComments
, 'guid_item')
4120 for Item
in GenList
:
4121 for CName
in Item
[0]:
4123 if CName
in Item
[1]:
4124 Comments
= '\n '.join(Item
[1][CName
])
4127 Entry
= Comments
+ '\n ' + CName
4128 AsBuiltInfDict
[Item
[2]].append(Entry
)
4129 PatchList
= parsePcdInfoFromMapFile(
4130 os
.path
.join(self
.OutputDir
, self
.Name
+ '.map'),
4131 os
.path
.join(self
.OutputDir
, self
.Name
+ '.efi')
4134 for Pcd
in PatchablePcds
:
4135 TokenCName
= Pcd
.TokenCName
4136 for PcdItem
in GlobalData
.MixedPcd
:
4137 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
4138 TokenCName
= PcdItem
[0]
4140 for PatchPcd
in PatchList
:
4141 if TokenCName
== PatchPcd
[0]:
4146 if Pcd
.DatumType
== 'BOOLEAN':
4147 BoolValue
= Pcd
.DefaultValue
.upper()
4148 if BoolValue
== 'TRUE':
4149 Pcd
.DefaultValue
= '1'
4150 elif BoolValue
== 'FALSE':
4151 Pcd
.DefaultValue
= '0'
4153 if Pcd
.DatumType
in ['UINT8', 'UINT16', 'UINT32', 'UINT64', 'BOOLEAN']:
4154 HexFormat
= '0x%02x'
4155 if Pcd
.DatumType
== 'UINT16':
4156 HexFormat
= '0x%04x'
4157 elif Pcd
.DatumType
== 'UINT32':
4158 HexFormat
= '0x%08x'
4159 elif Pcd
.DatumType
== 'UINT64':
4160 HexFormat
= '0x%016x'
4161 PcdValue
= HexFormat
% int(Pcd
.DefaultValue
, 0)
4163 if Pcd
.MaxDatumSize
is None or Pcd
.MaxDatumSize
== '':
4164 EdkLogger
.error("build", AUTOGEN_ERROR
,
4165 "Unknown [MaxDatumSize] of PCD [%s.%s]" % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
4167 ArraySize
= int(Pcd
.MaxDatumSize
, 0)
4168 PcdValue
= Pcd
.DefaultValue
4169 if PcdValue
[0] != '{':
4171 if PcdValue
[0] == 'L':
4173 PcdValue
= PcdValue
.lstrip('L')
4174 PcdValue
= eval(PcdValue
)
4176 for Index
in range(0, len(PcdValue
)):
4178 CharVal
= ord(PcdValue
[Index
])
4179 NewValue
= NewValue
+ '0x%02x' % (CharVal
& 0x00FF) + ', ' \
4180 + '0x%02x' % (CharVal
>> 8) + ', '
4182 NewValue
= NewValue
+ '0x%02x' % (ord(PcdValue
[Index
]) % 0x100) + ', '
4185 Padding
= Padding
* 2
4186 ArraySize
= ArraySize
/ 2
4187 if ArraySize
< (len(PcdValue
) + 1):
4188 EdkLogger
.error("build", AUTOGEN_ERROR
,
4189 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
4191 if ArraySize
> len(PcdValue
) + 1:
4192 NewValue
= NewValue
+ Padding
* (ArraySize
- len(PcdValue
) - 1)
4193 PcdValue
= NewValue
+ Padding
.strip().rstrip(',') + '}'
4194 elif len(PcdValue
.split(',')) <= ArraySize
:
4195 PcdValue
= PcdValue
.rstrip('}') + ', 0x00' * (ArraySize
- len(PcdValue
.split(',')))
4198 EdkLogger
.error("build", AUTOGEN_ERROR
,
4199 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
4201 PcdItem
= '%s.%s|%s|0x%X' % \
4202 (Pcd
.TokenSpaceGuidCName
, TokenCName
, PcdValue
, PatchPcd
[1])
4204 if (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in self
._PcdComments
:
4205 PcdComments
= '\n '.join(self
._PcdComments
[Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
])
4207 PcdItem
= PcdComments
+ '\n ' + PcdItem
4208 AsBuiltInfDict
['patchablepcd_item'].append(PcdItem
)
4211 for Pcd
in Pcds
+ VfrPcds
:
4216 TokenCName
= Pcd
.TokenCName
4217 for PcdItem
in GlobalData
.MixedPcd
:
4218 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
4219 TokenCName
= PcdItem
[0]
4221 if Pcd
.Type
== TAB_PCDS_DYNAMIC_EX_HII
:
4222 for SkuName
in Pcd
.SkuInfoList
:
4223 SkuInfo
= Pcd
.SkuInfoList
[SkuName
]
4224 SkuId
= SkuInfo
.SkuId
4225 HiiInfo
= '## %s|%s|%s' % (SkuInfo
.VariableName
, SkuInfo
.VariableGuid
, SkuInfo
.VariableOffset
)
4229 # Don't generate duplicated HII PCD
4231 if (SkuId
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in HiiPcds
:
4234 HiiPcds
.append((SkuId
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
4235 if (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in self
._PcdComments
:
4236 PcdCommentList
= self
._PcdComments
[Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
][:]
4240 for Index
, Comment
in enumerate(PcdCommentList
):
4241 for Usage
in UsageList
:
4242 if Comment
.find(Usage
) != -1:
4246 if UsageIndex
!= -1:
4247 PcdCommentList
[UsageIndex
] = '## %s %s %s' % (UsageStr
, HiiInfo
, PcdCommentList
[UsageIndex
].replace(UsageStr
, ''))
4249 PcdCommentList
.append('## UNDEFINED ' + HiiInfo
)
4250 PcdComments
= '\n '.join(PcdCommentList
)
4251 PcdEntry
= Pcd
.TokenSpaceGuidCName
+ '.' + TokenCName
4253 PcdEntry
= PcdComments
+ '\n ' + PcdEntry
4254 AsBuiltInfDict
['pcd_item'] += [PcdEntry
]
4255 for Item
in self
.BuildOption
:
4256 if 'FLAGS' in self
.BuildOption
[Item
]:
4257 AsBuiltInfDict
['flags_item'] += ['%s:%s_%s_%s_%s_FLAGS = %s' % (self
.ToolChainFamily
, self
.BuildTarget
, self
.ToolChain
, self
.Arch
, Item
, self
.BuildOption
[Item
]['FLAGS'].strip())]
4259 # Generated LibraryClasses section in comments.
4260 for Library
in self
.LibraryAutoGenList
:
4261 AsBuiltInfDict
['libraryclasses_item'] += [Library
.MetaFile
.File
.replace('\\', '/')]
4263 # Generated UserExtensions TianoCore section.
4264 # All tianocore user extensions are copied.
4266 for TianoCore
in self
._GetTianoCoreUserExtensionList
():
4267 UserExtStr
+= '\n'.join(TianoCore
)
4268 ExtensionFile
= os
.path
.join(self
.MetaFile
.Dir
, TianoCore
[1])
4269 if os
.path
.isfile(ExtensionFile
):
4270 shutil
.copy2(ExtensionFile
, self
.OutputDir
)
4271 AsBuiltInfDict
['userextension_tianocore_item'] = UserExtStr
4273 # Generated depex expression section in comments.
4274 AsBuiltInfDict
['depexsection_item'] = ''
4275 DepexExpresion
= self
._GetDepexExpresionString
()
4277 AsBuiltInfDict
['depexsection_item'] = DepexExpresion
4279 AsBuiltInf
= TemplateString()
4280 AsBuiltInf
.Append(gAsBuiltInfHeaderString
.Replace(AsBuiltInfDict
))
4282 SaveFileOnChange(os
.path
.join(self
.OutputDir
, self
.Name
+ '.inf'), str(AsBuiltInf
), False)
4284 self
.IsAsBuiltInfCreated
= True
4285 if GlobalData
.gBinCacheDest
:
4286 self
.CopyModuleToCache()
4288 def CopyModuleToCache(self
):
4289 FileDir
= path
.join(GlobalData
.gBinCacheDest
, self
.Arch
, self
.SourceDir
, self
.MetaFile
.BaseName
)
4290 CreateDirectory (FileDir
)
4291 HashFile
= path
.join(self
.BuildDir
, self
.Name
+ '.hash')
4292 ModuleFile
= path
.join(self
.OutputDir
, self
.Name
+ '.inf')
4293 if os
.path
.exists(HashFile
):
4294 shutil
.copy2(HashFile
, FileDir
)
4295 if os
.path
.exists(ModuleFile
):
4296 shutil
.copy2(ModuleFile
, FileDir
)
4297 if not self
.OutputFile
:
4298 Ma
= self
.Workspace
.BuildDatabase
[PathClass(ModuleFile
), self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
4299 self
.OutputFile
= Ma
.Binaries
4301 for File
in self
.OutputFile
:
4303 if not os
.path
.isabs(File
):
4304 File
= os
.path
.join(self
.OutputDir
, File
)
4305 if os
.path
.exists(File
):
4306 shutil
.copy2(File
, FileDir
)
4308 def AttemptModuleCacheCopy(self
):
4309 if self
.IsBinaryModule
:
4311 FileDir
= path
.join(GlobalData
.gBinCacheSource
, self
.Arch
, self
.SourceDir
, self
.MetaFile
.BaseName
)
4312 HashFile
= path
.join(FileDir
, self
.Name
+ '.hash')
4313 if os
.path
.exists(HashFile
):
4314 f
= open(HashFile
, 'r')
4315 CacheHash
= f
.read()
4317 if GlobalData
.gModuleHash
[self
.Arch
][self
.Name
]:
4318 if CacheHash
== GlobalData
.gModuleHash
[self
.Arch
][self
.Name
]:
4319 for root
, dir, files
in os
.walk(FileDir
):
4321 if self
.Name
+ '.hash' in f
:
4322 shutil
.copy2(HashFile
, self
.BuildDir
)
4324 File
= path
.join(root
, f
)
4325 shutil
.copy2(File
, self
.OutputDir
)
4326 if self
.Name
== "PcdPeim" or self
.Name
== "PcdDxe":
4327 CreatePcdDatabaseCode(self
, TemplateString(), TemplateString())
4331 ## Create makefile for the module and its dependent libraries
4333 # @param CreateLibraryMakeFile Flag indicating if or not the makefiles of
4334 # dependent libraries will be created
4336 def CreateMakeFile(self
, CreateLibraryMakeFile
=True, GenFfsList
= []):
4337 # Ignore generating makefile when it is a binary module
4338 if self
.IsBinaryModule
:
4341 if self
.IsMakeFileCreated
:
4343 self
.GenFfsList
= GenFfsList
4344 if not self
.IsLibrary
and CreateLibraryMakeFile
:
4345 for LibraryAutoGen
in self
.LibraryAutoGenList
:
4346 LibraryAutoGen
.CreateMakeFile()
4351 if len(self
.CustomMakefile
) == 0:
4352 Makefile
= GenMake
.ModuleMakefile(self
)
4354 Makefile
= GenMake
.CustomMakefile(self
)
4355 if Makefile
.Generate():
4356 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated makefile for module %s [%s]" %
4357 (self
.Name
, self
.Arch
))
4359 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of makefile for module %s [%s]" %
4360 (self
.Name
, self
.Arch
))
4362 self
.CreateTimeStamp(Makefile
)
4363 self
.IsMakeFileCreated
= True
4365 def CopyBinaryFiles(self
):
4366 for File
in self
.Module
.Binaries
:
4368 DstPath
= os
.path
.join(self
.OutputDir
, os
.path
.basename(SrcPath
))
4369 CopyLongFilePath(SrcPath
, DstPath
)
4370 ## Create autogen code for the module and its dependent libraries
4372 # @param CreateLibraryCodeFile Flag indicating if or not the code of
4373 # dependent libraries will be created
4375 def CreateCodeFile(self
, CreateLibraryCodeFile
=True):
4376 if self
.IsCodeFileCreated
:
4379 # Need to generate PcdDatabase even PcdDriver is binarymodule
4380 if self
.IsBinaryModule
and self
.PcdIsDriver
!= '':
4381 CreatePcdDatabaseCode(self
, TemplateString(), TemplateString())
4383 if self
.IsBinaryModule
:
4385 self
.CopyBinaryFiles()
4388 if not self
.IsLibrary
and CreateLibraryCodeFile
:
4389 for LibraryAutoGen
in self
.LibraryAutoGenList
:
4390 LibraryAutoGen
.CreateCodeFile()
4396 IgoredAutoGenList
= []
4398 for File
in self
.AutoGenFileList
:
4399 if GenC
.Generate(File
.Path
, self
.AutoGenFileList
[File
], File
.IsBinary
):
4400 #Ignore Edk AutoGen.c
4401 if self
.AutoGenVersion
< 0x00010005 and File
.Name
== 'AutoGen.c':
4404 AutoGenList
.append(str(File
))
4406 IgoredAutoGenList
.append(str(File
))
4408 # Skip the following code for EDK I inf
4409 if self
.AutoGenVersion
< 0x00010005:
4412 for ModuleType
in self
.DepexList
:
4413 # Ignore empty [depex] section or [depex] section for "USER_DEFINED" module
4414 if len(self
.DepexList
[ModuleType
]) == 0 or ModuleType
== "USER_DEFINED":
4417 Dpx
= GenDepex
.DependencyExpression(self
.DepexList
[ModuleType
], ModuleType
, True)
4418 DpxFile
= gAutoGenDepexFileName
% {"module_name" : self
.Name
}
4420 if len(Dpx
.PostfixNotation
) <> 0:
4421 self
.DepexGenerated
= True
4423 if Dpx
.Generate(path
.join(self
.OutputDir
, DpxFile
)):
4424 AutoGenList
.append(str(DpxFile
))
4426 IgoredAutoGenList
.append(str(DpxFile
))
4428 if IgoredAutoGenList
== []:
4429 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] files for module %s [%s]" %
4430 (" ".join(AutoGenList
), self
.Name
, self
.Arch
))
4431 elif AutoGenList
== []:
4432 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of [%s] files for module %s [%s]" %
4433 (" ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
4435 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] (skipped %s) files for module %s [%s]" %
4436 (" ".join(AutoGenList
), " ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
4438 self
.IsCodeFileCreated
= True
4441 ## Summarize the ModuleAutoGen objects of all libraries used by this module
4442 def _GetLibraryAutoGenList(self
):
4443 if self
._LibraryAutoGenList
is None:
4444 self
._LibraryAutoGenList
= []
4445 for Library
in self
.DependentLibraryList
:
4452 self
.PlatformInfo
.MetaFile
4454 if La
not in self
._LibraryAutoGenList
:
4455 self
._LibraryAutoGenList
.append(La
)
4456 for Lib
in La
.CodaTargetList
:
4457 self
._ApplyBuildRule
(Lib
.Target
, TAB_UNKNOWN_FILE
)
4458 return self
._LibraryAutoGenList
4460 def GenModuleHash(self
):
4461 if self
.Arch
not in GlobalData
.gModuleHash
:
4462 GlobalData
.gModuleHash
[self
.Arch
] = {}
4464 # Add Platform level hash
4465 m
.update(GlobalData
.gPlatformHash
)
4466 # Add Package level hash
4467 if self
.DependentPackageList
:
4468 for Pkg
in self
.DependentPackageList
:
4469 if Pkg
.PackageName
in GlobalData
.gPackageHash
[self
.Arch
]:
4470 m
.update(GlobalData
.gPackageHash
[self
.Arch
][Pkg
.PackageName
])
4473 if self
.LibraryAutoGenList
:
4474 for Lib
in self
.LibraryAutoGenList
:
4475 if Lib
.Name
not in GlobalData
.gModuleHash
[self
.Arch
]:
4477 m
.update(GlobalData
.gModuleHash
[self
.Arch
][Lib
.Name
])
4480 f
= open(str(self
.MetaFile
), 'r')
4484 # Add Module's source files
4485 if self
.SourceFileList
:
4486 for File
in self
.SourceFileList
:
4487 f
= open(str(File
), 'r')
4492 ModuleHashFile
= path
.join(self
.BuildDir
, self
.Name
+ ".hash")
4493 if self
.Name
not in GlobalData
.gModuleHash
[self
.Arch
]:
4494 GlobalData
.gModuleHash
[self
.Arch
][self
.Name
] = m
.hexdigest()
4495 if GlobalData
.gBinCacheSource
:
4496 CacheValid
= self
.AttemptModuleCacheCopy()
4499 return SaveFileOnChange(ModuleHashFile
, m
.hexdigest(), True)
4501 ## Decide whether we can skip the ModuleAutoGen process
4502 def CanSkipbyHash(self
):
4503 if GlobalData
.gUseHashCache
:
4504 return not self
.GenModuleHash()
4506 ## Decide whether we can skip the ModuleAutoGen process
4507 # If any source file is newer than the module than we cannot skip
4510 if not os
.path
.exists(self
.GetTimeStampPath()):
4512 #last creation time of the module
4513 DstTimeStamp
= os
.stat(self
.GetTimeStampPath())[8]
4515 SrcTimeStamp
= self
.Workspace
._SrcTimeStamp
4516 if SrcTimeStamp
> DstTimeStamp
:
4519 with
open(self
.GetTimeStampPath(),'r') as f
:
4521 source
= source
.rstrip('\n')
4522 if not os
.path
.exists(source
):
4524 if source
not in ModuleAutoGen
.TimeDict
:
4525 ModuleAutoGen
.TimeDict
[source
] = os
.stat(source
)[8]
4526 if ModuleAutoGen
.TimeDict
[source
] > DstTimeStamp
:
4530 def GetTimeStampPath(self
):
4531 if self
._TimeStampPath
is None:
4532 self
._TimeStampPath
= os
.path
.join(self
.MakeFileDir
, 'AutoGenTimeStamp')
4533 return self
._TimeStampPath
4534 def CreateTimeStamp(self
, Makefile
):
4538 FileSet
.add (self
.MetaFile
.Path
)
4540 for SourceFile
in self
.Module
.Sources
:
4541 FileSet
.add (SourceFile
.Path
)
4543 for Lib
in self
.DependentLibraryList
:
4544 FileSet
.add (Lib
.MetaFile
.Path
)
4546 for f
in self
.AutoGenDepSet
:
4547 FileSet
.add (f
.Path
)
4549 if os
.path
.exists (self
.GetTimeStampPath()):
4550 os
.remove (self
.GetTimeStampPath())
4551 with
open(self
.GetTimeStampPath(), 'w+') as file:
4555 Module
= property(_GetModule
)
4556 Name
= property(_GetBaseName
)
4557 Guid
= property(_GetGuid
)
4558 Version
= property(_GetVersion
)
4559 ModuleType
= property(_GetModuleType
)
4560 ComponentType
= property(_GetComponentType
)
4561 BuildType
= property(_GetBuildType
)
4562 PcdIsDriver
= property(_GetPcdIsDriver
)
4563 AutoGenVersion
= property(_GetAutoGenVersion
)
4564 Macros
= property(_GetMacros
)
4565 Specification
= property(_GetSpecification
)
4567 IsLibrary
= property(_IsLibrary
)
4568 IsBinaryModule
= property(_IsBinaryModule
)
4569 BuildDir
= property(_GetBuildDir
)
4570 OutputDir
= property(_GetOutputDir
)
4571 FfsOutputDir
= property(_GetFfsOutputDir
)
4572 DebugDir
= property(_GetDebugDir
)
4573 MakeFileDir
= property(_GetMakeFileDir
)
4574 CustomMakefile
= property(_GetCustomMakefile
)
4576 IncludePathList
= property(_GetIncludePathList
)
4577 IncludePathLength
= property(_GetIncludePathLength
)
4578 AutoGenFileList
= property(_GetAutoGenFileList
)
4579 UnicodeFileList
= property(_GetUnicodeFileList
)
4580 VfrFileList
= property(_GetVfrFileList
)
4581 SourceFileList
= property(_GetSourceFileList
)
4582 BinaryFileList
= property(_GetBinaryFiles
) # FileType : [File List]
4583 Targets
= property(_GetTargets
)
4584 IntroTargetList
= property(_GetIntroTargetList
)
4585 CodaTargetList
= property(_GetFinalTargetList
)
4586 FileTypes
= property(_GetFileTypes
)
4587 BuildRules
= property(_GetBuildRules
)
4588 IdfFileList
= property(_GetIdfFileList
)
4590 DependentPackageList
= property(_GetDependentPackageList
)
4591 DependentLibraryList
= property(_GetLibraryList
)
4592 LibraryAutoGenList
= property(_GetLibraryAutoGenList
)
4593 DerivedPackageList
= property(_GetDerivedPackageList
)
4595 ModulePcdList
= property(_GetModulePcdList
)
4596 LibraryPcdList
= property(_GetLibraryPcdList
)
4597 GuidList
= property(_GetGuidList
)
4598 ProtocolList
= property(_GetProtocolList
)
4599 PpiList
= property(_GetPpiList
)
4600 DepexList
= property(_GetDepexTokenList
)
4601 DxsFile
= property(_GetDxsFile
)
4602 DepexExpressionList
= property(_GetDepexExpressionTokenList
)
4603 BuildOption
= property(_GetModuleBuildOption
)
4604 BuildOptionIncPathList
= property(_GetBuildOptionIncPathList
)
4605 BuildCommand
= property(_GetBuildCommand
)
4607 FixedAtBuildPcds
= property(_GetFixedAtBuildPcds
)
4609 # This acts like the main() function for the script, unless it is 'import'ed into another script.
4610 if __name__
== '__main__':