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
]
418 SourcePcdDict
= {'DynamicEx':set(), 'PatchableInModule':set(),'Dynamic':set(),'FixedAtBuild':set()}
419 BinaryPcdDict
= {'DynamicEx':set(), 'PatchableInModule':set()}
420 SourcePcdDict_Keys
= SourcePcdDict
.keys()
421 BinaryPcdDict_Keys
= BinaryPcdDict
.keys()
423 # generate the SourcePcdDict and BinaryPcdDict
424 PGen
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
425 for BuildData
in PGen
.BuildDatabase
._CACHE
_.values():
426 if BuildData
.Arch
!= Arch
:
428 if BuildData
.MetaFile
.Ext
== '.inf':
429 for key
in BuildData
.Pcds
:
430 if BuildData
.Pcds
[key
].Pending
:
431 if key
in Platform
.Pcds
:
432 PcdInPlatform
= Platform
.Pcds
[key
]
433 if PcdInPlatform
.Type
not in [None, '']:
434 BuildData
.Pcds
[key
].Type
= PcdInPlatform
.Type
436 if BuildData
.MetaFile
in Platform
.Modules
:
437 PlatformModule
= Platform
.Modules
[str(BuildData
.MetaFile
)]
438 if key
in PlatformModule
.Pcds
:
439 PcdInPlatform
= PlatformModule
.Pcds
[key
]
440 if PcdInPlatform
.Type
not in [None, '']:
441 BuildData
.Pcds
[key
].Type
= PcdInPlatform
.Type
443 if 'DynamicEx' in BuildData
.Pcds
[key
].Type
:
444 if BuildData
.IsBinaryModule
:
445 BinaryPcdDict
['DynamicEx'].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
447 SourcePcdDict
['DynamicEx'].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
449 elif 'PatchableInModule' in BuildData
.Pcds
[key
].Type
:
450 if BuildData
.MetaFile
.Ext
== '.inf':
451 if BuildData
.IsBinaryModule
:
452 BinaryPcdDict
['PatchableInModule'].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
454 SourcePcdDict
['PatchableInModule'].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
456 elif 'Dynamic' in BuildData
.Pcds
[key
].Type
:
457 SourcePcdDict
['Dynamic'].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
458 elif 'FixedAtBuild' in BuildData
.Pcds
[key
].Type
:
459 SourcePcdDict
['FixedAtBuild'].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
463 # A PCD can only use one type for all source modules
465 for i
in SourcePcdDict_Keys
:
466 for j
in SourcePcdDict_Keys
:
468 Intersections
= SourcePcdDict
[i
].intersection(SourcePcdDict
[j
])
469 if len(Intersections
) > 0:
473 "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
),
474 ExtraData
="%s" % '\n\t'.join([str(P
[1]+'.'+P
[0]) for P
in Intersections
])
480 # intersection the BinaryPCD for Mixed PCD
482 for i
in BinaryPcdDict_Keys
:
483 for j
in BinaryPcdDict_Keys
:
485 Intersections
= BinaryPcdDict
[i
].intersection(BinaryPcdDict
[j
])
486 for item
in Intersections
:
487 NewPcd1
= (item
[0] + '_' + i
, item
[1])
488 NewPcd2
= (item
[0] + '_' + j
, item
[1])
489 if item
not in GlobalData
.MixedPcd
:
490 GlobalData
.MixedPcd
[item
] = [NewPcd1
, NewPcd2
]
492 if NewPcd1
not in GlobalData
.MixedPcd
[item
]:
493 GlobalData
.MixedPcd
[item
].append(NewPcd1
)
494 if NewPcd2
not in GlobalData
.MixedPcd
[item
]:
495 GlobalData
.MixedPcd
[item
].append(NewPcd2
)
500 # intersection the SourcePCD and BinaryPCD for Mixed PCD
502 for i
in SourcePcdDict_Keys
:
503 for j
in BinaryPcdDict_Keys
:
505 Intersections
= SourcePcdDict
[i
].intersection(BinaryPcdDict
[j
])
506 for item
in Intersections
:
507 NewPcd1
= (item
[0] + '_' + i
, item
[1])
508 NewPcd2
= (item
[0] + '_' + j
, item
[1])
509 if item
not in GlobalData
.MixedPcd
:
510 GlobalData
.MixedPcd
[item
] = [NewPcd1
, NewPcd2
]
512 if NewPcd1
not in GlobalData
.MixedPcd
[item
]:
513 GlobalData
.MixedPcd
[item
].append(NewPcd1
)
514 if NewPcd2
not in GlobalData
.MixedPcd
[item
]:
515 GlobalData
.MixedPcd
[item
].append(NewPcd2
)
519 for BuildData
in PGen
.BuildDatabase
._CACHE
_.values():
520 if BuildData
.Arch
!= Arch
:
522 for key
in BuildData
.Pcds
:
523 for SinglePcd
in GlobalData
.MixedPcd
:
524 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) == SinglePcd
:
525 for item
in GlobalData
.MixedPcd
[SinglePcd
]:
526 Pcd_Type
= item
[0].split('_')[-1]
527 if (Pcd_Type
== BuildData
.Pcds
[key
].Type
) or (Pcd_Type
== TAB_PCDS_DYNAMIC_EX
and BuildData
.Pcds
[key
].Type
in GenC
.gDynamicExPcd
) or \
528 (Pcd_Type
== TAB_PCDS_DYNAMIC
and BuildData
.Pcds
[key
].Type
in GenC
.gDynamicPcd
):
529 Value
= BuildData
.Pcds
[key
]
530 Value
.TokenCName
= BuildData
.Pcds
[key
].TokenCName
+ '_' + Pcd_Type
532 newkey
= (Value
.TokenCName
, key
[1])
534 newkey
= (Value
.TokenCName
, key
[1], key
[2])
535 del BuildData
.Pcds
[key
]
536 BuildData
.Pcds
[newkey
] = Value
544 # handle the mixed pcd in FDF file
546 if key
in GlobalData
.MixedPcd
:
549 for item
in GlobalData
.MixedPcd
[key
]:
552 #Collect package set information from INF of FDF
554 for Inf
in ModuleList
:
555 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
556 if ModuleFile
in Platform
.Modules
:
558 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, Target
, Toolchain
]
559 PkgSet
.update(ModuleData
.Packages
)
560 Pkgs
= list(PkgSet
) + list(PGen
.PackageList
)
565 DecPcds
[Pcd
[0], Pcd
[1]] = Pkg
.Pcds
[Pcd
]
566 DecPcdsKey
.add((Pcd
[0], Pcd
[1], Pcd
[2]))
568 Platform
.SkuName
= self
.SkuId
569 for Name
, Guid
in PcdSet
:
570 if (Name
, Guid
) not in DecPcds
:
574 "PCD (%s.%s) used in FDF is not declared in DEC files." % (Guid
, Name
),
575 File
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][0],
576 Line
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][1]
579 # Check whether Dynamic or DynamicEx PCD used in FDF file. If used, build break and give a error message.
580 if (Name
, Guid
, TAB_PCDS_FIXED_AT_BUILD
) in DecPcdsKey \
581 or (Name
, Guid
, TAB_PCDS_PATCHABLE_IN_MODULE
) in DecPcdsKey \
582 or (Name
, Guid
, TAB_PCDS_FEATURE_FLAG
) in DecPcdsKey
:
583 Platform
.AddPcd(Name
, Guid
, PcdSet
[Name
, Guid
])
585 elif (Name
, Guid
, TAB_PCDS_DYNAMIC
) in DecPcdsKey
or (Name
, Guid
, TAB_PCDS_DYNAMIC_EX
) in DecPcdsKey
:
589 "Using Dynamic or DynamicEx type of PCD [%s.%s] in FDF file is not allowed." % (Guid
, Name
),
590 File
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][0],
591 Line
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][1]
594 Pa
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
596 # Explicitly collect platform's dynamic PCDs
598 Pa
.CollectPlatformDynamicPcds()
599 Pa
.CollectFixedAtBuildPcds()
600 self
.AutoGenObjectList
.append(Pa
)
603 # Generate Package level hash value
605 GlobalData
.gPackageHash
[Arch
] = {}
606 if GlobalData
.gUseHashCache
:
608 self
._GenPkgLevelHash
(Pkg
)
611 # Check PCDs token value conflict in each DEC file.
613 self
._CheckAllPcdsTokenValueConflict
()
616 # Check PCD type and definition between DSC and DEC
618 self
._CheckPcdDefineAndType
()
621 # self._CheckDuplicateInFV(Fdf)
624 # Create BuildOptions Macro & PCD metafile, also add the Active Platform and FDF file.
626 content
= 'gCommandLineDefines: '
627 content
+= str(GlobalData
.gCommandLineDefines
)
628 content
+= os
.linesep
629 content
+= 'BuildOptionPcd: '
630 content
+= str(GlobalData
.BuildOptionPcd
)
631 content
+= os
.linesep
632 content
+= 'Active Platform: '
633 content
+= str(self
.Platform
)
634 content
+= os
.linesep
636 content
+= 'Flash Image Definition: '
637 content
+= str(self
.FdfFile
)
638 content
+= os
.linesep
639 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'BuildOptions'), content
, False)
642 # Create PcdToken Number file for Dynamic/DynamicEx Pcd.
644 PcdTokenNumber
= 'PcdTokenNumber: '
645 if Pa
.PcdTokenNumber
:
646 if Pa
.DynamicPcdList
:
647 for Pcd
in Pa
.DynamicPcdList
:
648 PcdTokenNumber
+= os
.linesep
649 PcdTokenNumber
+= str((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
))
650 PcdTokenNumber
+= ' : '
651 PcdTokenNumber
+= str(Pa
.PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
])
652 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'PcdTokenNumber'), PcdTokenNumber
, False)
655 # Get set of workspace metafiles
657 AllWorkSpaceMetaFiles
= self
._GetMetaFiles
(Target
, Toolchain
, Arch
)
660 # Retrieve latest modified time of all metafiles
663 for f
in AllWorkSpaceMetaFiles
:
664 if os
.stat(f
)[8] > SrcTimeStamp
:
665 SrcTimeStamp
= os
.stat(f
)[8]
666 self
._SrcTimeStamp
= SrcTimeStamp
668 if GlobalData
.gUseHashCache
:
670 for files
in AllWorkSpaceMetaFiles
:
671 if files
.endswith('.dec'):
677 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'AutoGen.hash'), m
.hexdigest(), True)
678 GlobalData
.gPlatformHash
= m
.hexdigest()
681 # Write metafile list to build directory
683 AutoGenFilePath
= os
.path
.join(self
.BuildDir
, 'AutoGen')
684 if os
.path
.exists (AutoGenFilePath
):
685 os
.remove(AutoGenFilePath
)
686 if not os
.path
.exists(self
.BuildDir
):
687 os
.makedirs(self
.BuildDir
)
688 with
open(os
.path
.join(self
.BuildDir
, 'AutoGen'), 'w+') as file:
689 for f
in AllWorkSpaceMetaFiles
:
693 def _GenPkgLevelHash(self
, Pkg
):
694 PkgDir
= os
.path
.join(self
.BuildDir
, Pkg
.Arch
, Pkg
.PackageName
)
695 CreateDirectory(PkgDir
)
696 HashFile
= os
.path
.join(PkgDir
, Pkg
.PackageName
+ '.hash')
698 # Get .dec file's hash value
699 f
= open(Pkg
.MetaFile
.Path
, 'r')
703 # Get include files hash value
705 for inc
in Pkg
.Includes
:
706 for Root
, Dirs
, Files
in os
.walk(str(inc
)):
708 File_Path
= os
.path
.join(Root
, File
)
709 f
= open(File_Path
, 'r')
713 SaveFileOnChange(HashFile
, m
.hexdigest(), True)
714 if Pkg
.PackageName
not in GlobalData
.gPackageHash
[Pkg
.Arch
]:
715 GlobalData
.gPackageHash
[Pkg
.Arch
][Pkg
.PackageName
] = m
.hexdigest()
717 def _GetMetaFiles(self
, Target
, Toolchain
, Arch
):
718 AllWorkSpaceMetaFiles
= set()
723 AllWorkSpaceMetaFiles
.add (self
.FdfFile
.Path
)
725 FdfFiles
= GlobalData
.gFdfParser
.GetAllIncludedFile()
727 AllWorkSpaceMetaFiles
.add (f
.FileName
)
731 AllWorkSpaceMetaFiles
.add(self
.MetaFile
.Path
)
734 # add build_rule.txt & tools_def.txt
736 AllWorkSpaceMetaFiles
.add(os
.path
.join(GlobalData
.gConfDirectory
, gDefaultBuildRuleFile
))
737 AllWorkSpaceMetaFiles
.add(os
.path
.join(GlobalData
.gConfDirectory
, gDefaultToolsDefFile
))
739 # add BuildOption metafile
741 AllWorkSpaceMetaFiles
.add(os
.path
.join(self
.BuildDir
, 'BuildOptions'))
743 # add PcdToken Number file for Dynamic/DynamicEx Pcd
745 AllWorkSpaceMetaFiles
.add(os
.path
.join(self
.BuildDir
, 'PcdTokenNumber'))
747 for Arch
in self
.ArchList
:
748 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
749 PGen
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
754 for Package
in PGen
.PackageList
:
755 AllWorkSpaceMetaFiles
.add(Package
.MetaFile
.Path
)
760 for filePath
in Platform
._RawData
.IncludedFiles
:
761 AllWorkSpaceMetaFiles
.add(filePath
.Path
)
763 return AllWorkSpaceMetaFiles
765 ## _CheckDuplicateInFV() method
767 # Check whether there is duplicate modules/files exist in FV section.
768 # The check base on the file GUID;
770 def _CheckDuplicateInFV(self
, Fdf
):
771 for Fv
in Fdf
.Profile
.FvDict
:
773 for FfsFile
in Fdf
.Profile
.FvDict
[Fv
].FfsList
:
774 if FfsFile
.InfFileName
and FfsFile
.NameGuid
is None:
779 for Pa
in self
.AutoGenObjectList
:
782 for Module
in Pa
.ModuleAutoGenList
:
783 if path
.normpath(Module
.MetaFile
.File
) == path
.normpath(FfsFile
.InfFileName
):
785 if not Module
.Guid
.upper() in _GuidDict
.keys():
786 _GuidDict
[Module
.Guid
.upper()] = FfsFile
789 EdkLogger
.error("build",
791 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile
.CurrentLineNum
,
792 FfsFile
.CurrentLineContent
,
793 _GuidDict
[Module
.Guid
.upper()].CurrentLineNum
,
794 _GuidDict
[Module
.Guid
.upper()].CurrentLineContent
,
795 Module
.Guid
.upper()),
796 ExtraData
=self
.FdfFile
)
798 # Some INF files not have entity in DSC file.
801 if FfsFile
.InfFileName
.find('$') == -1:
802 InfPath
= NormPath(FfsFile
.InfFileName
)
803 if not os
.path
.exists(InfPath
):
804 EdkLogger
.error('build', GENFDS_ERROR
, "Non-existant Module %s !" % (FfsFile
.InfFileName
))
806 PathClassObj
= PathClass(FfsFile
.InfFileName
, self
.WorkspaceDir
)
808 # Here we just need to get FILE_GUID from INF file, use 'COMMON' as ARCH attribute. and use
809 # BuildObject from one of AutoGenObjectList is enough.
811 InfObj
= self
.AutoGenObjectList
[0].BuildDatabase
.WorkspaceDb
.BuildObject
[PathClassObj
, 'COMMON', self
.BuildTarget
, self
.ToolChain
]
812 if not InfObj
.Guid
.upper() in _GuidDict
.keys():
813 _GuidDict
[InfObj
.Guid
.upper()] = FfsFile
815 EdkLogger
.error("build",
817 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile
.CurrentLineNum
,
818 FfsFile
.CurrentLineContent
,
819 _GuidDict
[InfObj
.Guid
.upper()].CurrentLineNum
,
820 _GuidDict
[InfObj
.Guid
.upper()].CurrentLineContent
,
821 InfObj
.Guid
.upper()),
822 ExtraData
=self
.FdfFile
)
825 if FfsFile
.NameGuid
is not None:
827 # If the NameGuid reference a PCD name.
828 # The style must match: PCD(xxxx.yyy)
830 if gPCDAsGuidPattern
.match(FfsFile
.NameGuid
):
832 # Replace the PCD value.
834 _PcdName
= FfsFile
.NameGuid
.lstrip("PCD(").rstrip(")")
836 for Pa
in self
.AutoGenObjectList
:
838 for PcdItem
in Pa
.AllPcdList
:
839 if (PcdItem
.TokenSpaceGuidCName
+ "." + PcdItem
.TokenCName
) == _PcdName
:
841 # First convert from CFormatGuid to GUID string
843 _PcdGuidString
= GuidStructureStringToGuidString(PcdItem
.DefaultValue
)
845 if not _PcdGuidString
:
847 # Then try Byte array.
849 _PcdGuidString
= GuidStructureByteArrayToGuidString(PcdItem
.DefaultValue
)
851 if not _PcdGuidString
:
853 # Not Byte array or CFormat GUID, raise error.
855 EdkLogger
.error("build",
857 "The format of PCD value is incorrect. PCD: %s , Value: %s\n" % (_PcdName
, PcdItem
.DefaultValue
),
858 ExtraData
=self
.FdfFile
)
860 if not _PcdGuidString
.upper() in _GuidDict
.keys():
861 _GuidDict
[_PcdGuidString
.upper()] = FfsFile
865 EdkLogger
.error("build",
867 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile
.CurrentLineNum
,
868 FfsFile
.CurrentLineContent
,
869 _GuidDict
[_PcdGuidString
.upper()].CurrentLineNum
,
870 _GuidDict
[_PcdGuidString
.upper()].CurrentLineContent
,
871 FfsFile
.NameGuid
.upper()),
872 ExtraData
=self
.FdfFile
)
874 if not FfsFile
.NameGuid
.upper() in _GuidDict
.keys():
875 _GuidDict
[FfsFile
.NameGuid
.upper()] = FfsFile
878 # Two raw file GUID conflict.
880 EdkLogger
.error("build",
882 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile
.CurrentLineNum
,
883 FfsFile
.CurrentLineContent
,
884 _GuidDict
[FfsFile
.NameGuid
.upper()].CurrentLineNum
,
885 _GuidDict
[FfsFile
.NameGuid
.upper()].CurrentLineContent
,
886 FfsFile
.NameGuid
.upper()),
887 ExtraData
=self
.FdfFile
)
890 def _CheckPcdDefineAndType(self
):
892 "FixedAtBuild", "PatchableInModule", "FeatureFlag",
893 "Dynamic", #"DynamicHii", "DynamicVpd",
894 "DynamicEx", # "DynamicExHii", "DynamicExVpd"
897 # This dict store PCDs which are not used by any modules with specified arches
898 UnusedPcd
= OrderedDict()
899 for Pa
in self
.AutoGenObjectList
:
900 # Key of DSC's Pcds dictionary is PcdCName, TokenSpaceGuid
901 for Pcd
in Pa
.Platform
.Pcds
:
902 PcdType
= Pa
.Platform
.Pcds
[Pcd
].Type
904 # If no PCD type, this PCD comes from FDF
908 # Try to remove Hii and Vpd suffix
909 if PcdType
.startswith("DynamicEx"):
910 PcdType
= "DynamicEx"
911 elif PcdType
.startswith("Dynamic"):
914 for Package
in Pa
.PackageList
:
915 # Key of DEC's Pcds dictionary is PcdCName, TokenSpaceGuid, PcdType
916 if (Pcd
[0], Pcd
[1], PcdType
) in Package
.Pcds
:
918 for Type
in PcdTypeList
:
919 if (Pcd
[0], Pcd
[1], Type
) in Package
.Pcds
:
923 "Type [%s] of PCD [%s.%s] in DSC file doesn't match the type [%s] defined in DEC file." \
924 % (Pa
.Platform
.Pcds
[Pcd
].Type
, Pcd
[1], Pcd
[0], Type
),
929 UnusedPcd
.setdefault(Pcd
, []).append(Pa
.Arch
)
931 for Pcd
in UnusedPcd
:
934 "The PCD was not specified by any INF module in the platform for the given architecture.\n"
935 "\tPCD: [%s.%s]\n\tPlatform: [%s]\n\tArch: %s"
936 % (Pcd
[1], Pcd
[0], os
.path
.basename(str(self
.MetaFile
)), str(UnusedPcd
[Pcd
])),
941 return "%s [%s]" % (self
.MetaFile
, ", ".join(self
.ArchList
))
943 ## Return the directory to store FV files
945 if self
._FvDir
is None:
946 self
._FvDir
= path
.join(self
.BuildDir
, 'FV')
949 ## Return the directory to store all intermediate and final files built
950 def _GetBuildDir(self
):
951 if self
._BuildDir
is None:
952 return self
.AutoGenObjectList
[0].BuildDir
954 ## Return the build output directory platform specifies
955 def _GetOutputDir(self
):
956 return self
.Platform
.OutputDirectory
958 ## Return platform name
960 return self
.Platform
.PlatformName
962 ## Return meta-file GUID
964 return self
.Platform
.Guid
966 ## Return platform version
967 def _GetVersion(self
):
968 return self
.Platform
.Version
970 ## Return paths of tools
971 def _GetToolDefinition(self
):
972 return self
.AutoGenObjectList
[0].ToolDefinition
974 ## Return directory of platform makefile
976 # @retval string Makefile directory
978 def _GetMakeFileDir(self
):
979 if self
._MakeFileDir
is None:
980 self
._MakeFileDir
= self
.BuildDir
981 return self
._MakeFileDir
983 ## Return build command string
985 # @retval string Build command string
987 def _GetBuildCommand(self
):
988 if self
._BuildCommand
is None:
989 # BuildCommand should be all the same. So just get one from platform AutoGen
990 self
._BuildCommand
= self
.AutoGenObjectList
[0].BuildCommand
991 return self
._BuildCommand
993 ## Check the PCDs token value conflict in each DEC file.
995 # Will cause build break and raise error message while two PCDs conflict.
999 def _CheckAllPcdsTokenValueConflict(self
):
1000 for Pa
in self
.AutoGenObjectList
:
1001 for Package
in Pa
.PackageList
:
1002 PcdList
= Package
.Pcds
.values()
1003 PcdList
.sort(lambda x
, y
: cmp(int(x
.TokenValue
, 0), int(y
.TokenValue
, 0)))
1005 while (Count
< len(PcdList
) - 1) :
1006 Item
= PcdList
[Count
]
1007 ItemNext
= PcdList
[Count
+ 1]
1009 # Make sure in the same token space the TokenValue should be unique
1011 if (int(Item
.TokenValue
, 0) == int(ItemNext
.TokenValue
, 0)):
1012 SameTokenValuePcdList
= []
1013 SameTokenValuePcdList
.append(Item
)
1014 SameTokenValuePcdList
.append(ItemNext
)
1015 RemainPcdListLength
= len(PcdList
) - Count
- 2
1016 for ValueSameCount
in range(RemainPcdListLength
):
1017 if int(PcdList
[len(PcdList
) - RemainPcdListLength
+ ValueSameCount
].TokenValue
, 0) == int(Item
.TokenValue
, 0):
1018 SameTokenValuePcdList
.append(PcdList
[len(PcdList
) - RemainPcdListLength
+ ValueSameCount
])
1022 # Sort same token value PCD list with TokenGuid and TokenCName
1024 SameTokenValuePcdList
.sort(lambda x
, y
: cmp("%s.%s" % (x
.TokenSpaceGuidCName
, x
.TokenCName
), "%s.%s" % (y
.TokenSpaceGuidCName
, y
.TokenCName
)))
1025 SameTokenValuePcdListCount
= 0
1026 while (SameTokenValuePcdListCount
< len(SameTokenValuePcdList
) - 1):
1028 TemListItem
= SameTokenValuePcdList
[SameTokenValuePcdListCount
]
1029 TemListItemNext
= SameTokenValuePcdList
[SameTokenValuePcdListCount
+ 1]
1031 if (TemListItem
.TokenSpaceGuidCName
== TemListItemNext
.TokenSpaceGuidCName
) and (TemListItem
.TokenCName
!= TemListItemNext
.TokenCName
):
1032 for PcdItem
in GlobalData
.MixedPcd
:
1033 if (TemListItem
.TokenCName
, TemListItem
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
] or \
1034 (TemListItemNext
.TokenCName
, TemListItemNext
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
1040 "The TokenValue [%s] of PCD [%s.%s] is conflict with: [%s.%s] in %s"\
1041 % (TemListItem
.TokenValue
, TemListItem
.TokenSpaceGuidCName
, TemListItem
.TokenCName
, TemListItemNext
.TokenSpaceGuidCName
, TemListItemNext
.TokenCName
, Package
),
1044 SameTokenValuePcdListCount
+= 1
1045 Count
+= SameTokenValuePcdListCount
1048 PcdList
= Package
.Pcds
.values()
1049 PcdList
.sort(lambda x
, y
: cmp("%s.%s" % (x
.TokenSpaceGuidCName
, x
.TokenCName
), "%s.%s" % (y
.TokenSpaceGuidCName
, y
.TokenCName
)))
1051 while (Count
< len(PcdList
) - 1) :
1052 Item
= PcdList
[Count
]
1053 ItemNext
= PcdList
[Count
+ 1]
1055 # Check PCDs with same TokenSpaceGuidCName.TokenCName have same token value as well.
1057 if (Item
.TokenSpaceGuidCName
== ItemNext
.TokenSpaceGuidCName
) and (Item
.TokenCName
== ItemNext
.TokenCName
) and (int(Item
.TokenValue
, 0) != int(ItemNext
.TokenValue
, 0)):
1061 "The TokenValue [%s] of PCD [%s.%s] in %s defined in two places should be same as well."\
1062 % (Item
.TokenValue
, Item
.TokenSpaceGuidCName
, Item
.TokenCName
, Package
),
1066 ## Generate fds command
1067 def _GenFdsCommand(self
):
1068 return (GenMake
.TopLevelMakefile(self
)._TEMPLATE
_.Replace(GenMake
.TopLevelMakefile(self
)._TemplateDict
)).strip()
1070 ## Create makefile for the platform and modules in it
1072 # @param CreateDepsMakeFile Flag indicating if the makefile for
1073 # modules will be created as well
1075 def CreateMakeFile(self
, CreateDepsMakeFile
=False):
1076 if CreateDepsMakeFile
:
1077 for Pa
in self
.AutoGenObjectList
:
1078 Pa
.CreateMakeFile(CreateDepsMakeFile
)
1080 ## Create autogen code for platform and modules
1082 # Since there's no autogen code for platform, this method will do nothing
1083 # if CreateModuleCodeFile is set to False.
1085 # @param CreateDepsCodeFile Flag indicating if creating module's
1086 # autogen code file or not
1088 def CreateCodeFile(self
, CreateDepsCodeFile
=False):
1089 if not CreateDepsCodeFile
:
1091 for Pa
in self
.AutoGenObjectList
:
1092 Pa
.CreateCodeFile(CreateDepsCodeFile
)
1094 ## Create AsBuilt INF file the platform
1096 def CreateAsBuiltInf(self
):
1099 Name
= property(_GetName
)
1100 Guid
= property(_GetGuid
)
1101 Version
= property(_GetVersion
)
1102 OutputDir
= property(_GetOutputDir
)
1104 ToolDefinition
= property(_GetToolDefinition
) # toolcode : tool path
1106 BuildDir
= property(_GetBuildDir
)
1107 FvDir
= property(_GetFvDir
)
1108 MakeFileDir
= property(_GetMakeFileDir
)
1109 BuildCommand
= property(_GetBuildCommand
)
1110 GenFdsCommand
= property(_GenFdsCommand
)
1112 ## AutoGen class for platform
1114 # PlatformAutoGen class will process the original information in platform
1115 # file in order to generate makefile for platform.
1117 class PlatformAutoGen(AutoGen
):
1118 # call super().__init__ then call the worker function with different parameter count
1119 def __init__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
1123 super(PlatformAutoGen
, self
).__init
__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
1124 self
._InitWorker
(Workspace
, MetaFile
, Target
, Toolchain
, Arch
)
1127 # Used to store all PCDs for both PEI and DXE phase, in order to generate
1128 # correct PCD database
1131 _NonDynaPcdList_
= []
1135 # The priority list while override build option
1137 PrioList
= {"0x11111" : 16, # TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE (Highest)
1138 "0x01111" : 15, # ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
1139 "0x10111" : 14, # TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE
1140 "0x00111" : 13, # ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE
1141 "0x11011" : 12, # TARGET_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
1142 "0x01011" : 11, # ******_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
1143 "0x10011" : 10, # TARGET_*********_****_COMMANDTYPE_ATTRIBUTE
1144 "0x00011" : 9, # ******_*********_****_COMMANDTYPE_ATTRIBUTE
1145 "0x11101" : 8, # TARGET_TOOLCHAIN_ARCH_***********_ATTRIBUTE
1146 "0x01101" : 7, # ******_TOOLCHAIN_ARCH_***********_ATTRIBUTE
1147 "0x10101" : 6, # TARGET_*********_ARCH_***********_ATTRIBUTE
1148 "0x00101" : 5, # ******_*********_ARCH_***********_ATTRIBUTE
1149 "0x11001" : 4, # TARGET_TOOLCHAIN_****_***********_ATTRIBUTE
1150 "0x01001" : 3, # ******_TOOLCHAIN_****_***********_ATTRIBUTE
1151 "0x10001" : 2, # TARGET_*********_****_***********_ATTRIBUTE
1152 "0x00001" : 1} # ******_*********_****_***********_ATTRIBUTE (Lowest)
1154 ## Initialize PlatformAutoGen
1157 # @param Workspace WorkspaceAutoGen object
1158 # @param PlatformFile Platform file (DSC file)
1159 # @param Target Build target (DEBUG, RELEASE)
1160 # @param Toolchain Name of tool chain
1161 # @param Arch arch of the platform supports
1163 def _InitWorker(self
, Workspace
, PlatformFile
, Target
, Toolchain
, Arch
):
1164 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen platform [%s] [%s]" % (PlatformFile
, Arch
))
1165 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (PlatformFile
, Arch
, Toolchain
, Target
)
1167 self
.MetaFile
= PlatformFile
1168 self
.Workspace
= Workspace
1169 self
.WorkspaceDir
= Workspace
.WorkspaceDir
1170 self
.ToolChain
= Toolchain
1171 self
.BuildTarget
= Target
1173 self
.SourceDir
= PlatformFile
.SubDir
1174 self
.SourceOverrideDir
= None
1175 self
.FdTargetList
= self
.Workspace
.FdTargetList
1176 self
.FvTargetList
= self
.Workspace
.FvTargetList
1177 self
.AllPcdList
= []
1178 # get the original module/package/platform objects
1179 self
.BuildDatabase
= Workspace
.BuildDatabase
1180 self
.DscBuildDataObj
= Workspace
.Platform
1181 self
._GuidDict
= Workspace
._GuidDict
1183 # flag indicating if the makefile/C-code file has been created or not
1184 self
.IsMakeFileCreated
= False
1185 self
.IsCodeFileCreated
= False
1187 self
._Platform
= None
1190 self
._Version
= None
1192 self
._BuildRule
= None
1193 self
._SourceDir
= None
1194 self
._BuildDir
= None
1195 self
._OutputDir
= None
1197 self
._MakeFileDir
= None
1198 self
._FdfFile
= None
1200 self
._PcdTokenNumber
= None # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
1201 self
._DynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1202 self
._NonDynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1203 self
._NonDynamicPcdDict
= {}
1205 self
._ToolDefinitions
= None
1206 self
._ToolDefFile
= None # toolcode : tool path
1207 self
._ToolChainFamily
= None
1208 self
._BuildRuleFamily
= None
1209 self
._BuildOption
= None # toolcode : option
1210 self
._EdkBuildOption
= None # edktoolcode : option
1211 self
._EdkIIBuildOption
= None # edkiitoolcode : option
1212 self
._PackageList
= None
1213 self
._ModuleAutoGenList
= None
1214 self
._LibraryAutoGenList
= None
1215 self
._BuildCommand
= None
1216 self
._AsBuildInfList
= []
1217 self
._AsBuildModuleList
= []
1219 self
.VariableInfo
= None
1221 if GlobalData
.gFdfParser
is not None:
1222 self
._AsBuildInfList
= GlobalData
.gFdfParser
.Profile
.InfList
1223 for Inf
in self
._AsBuildInfList
:
1224 InfClass
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, self
.Arch
)
1225 M
= self
.BuildDatabase
[InfClass
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1226 if not M
.IsSupportedArch
:
1228 self
._AsBuildModuleList
.append(InfClass
)
1229 # get library/modules for build
1230 self
.LibraryBuildDirectoryList
= []
1231 self
.ModuleBuildDirectoryList
= []
1236 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
1238 ## Create autogen code for platform and modules
1240 # Since there's no autogen code for platform, this method will do nothing
1241 # if CreateModuleCodeFile is set to False.
1243 # @param CreateModuleCodeFile Flag indicating if creating module's
1244 # autogen code file or not
1246 def CreateCodeFile(self
, CreateModuleCodeFile
=False):
1247 # only module has code to be greated, so do nothing if CreateModuleCodeFile is False
1248 if self
.IsCodeFileCreated
or not CreateModuleCodeFile
:
1251 for Ma
in self
.ModuleAutoGenList
:
1252 Ma
.CreateCodeFile(True)
1254 # don't do this twice
1255 self
.IsCodeFileCreated
= True
1257 ## Generate Fds Command
1258 def _GenFdsCommand(self
):
1259 return self
.Workspace
.GenFdsCommand
1261 ## Create makefile for the platform and mdoules in it
1263 # @param CreateModuleMakeFile Flag indicating if the makefile for
1264 # modules will be created as well
1266 def CreateMakeFile(self
, CreateModuleMakeFile
=False, FfsCommand
= {}):
1267 if CreateModuleMakeFile
:
1268 for ModuleFile
in self
.Platform
.Modules
:
1269 Ma
= ModuleAutoGen(self
.Workspace
, ModuleFile
, self
.BuildTarget
,
1270 self
.ToolChain
, self
.Arch
, self
.MetaFile
)
1271 if (ModuleFile
.File
, self
.Arch
) in FfsCommand
:
1272 Ma
.CreateMakeFile(True, FfsCommand
[ModuleFile
.File
, self
.Arch
])
1274 Ma
.CreateMakeFile(True)
1275 #Ma.CreateAsBuiltInf()
1277 # no need to create makefile for the platform more than once
1278 if self
.IsMakeFileCreated
:
1281 # create library/module build dirs for platform
1282 Makefile
= GenMake
.PlatformMakefile(self
)
1283 self
.LibraryBuildDirectoryList
= Makefile
.GetLibraryBuildDirectoryList()
1284 self
.ModuleBuildDirectoryList
= Makefile
.GetModuleBuildDirectoryList()
1286 self
.IsMakeFileCreated
= True
1288 ## Deal with Shared FixedAtBuild Pcds
1290 def CollectFixedAtBuildPcds(self
):
1291 for LibAuto
in self
.LibraryAutoGenList
:
1292 FixedAtBuildPcds
= {}
1293 ShareFixedAtBuildPcdsSameValue
= {}
1294 for Module
in LibAuto
._ReferenceModules
:
1295 for Pcd
in Module
.FixedAtBuildPcds
+ LibAuto
.FixedAtBuildPcds
:
1296 key
= ".".join((Pcd
.TokenSpaceGuidCName
,Pcd
.TokenCName
))
1297 if key
not in FixedAtBuildPcds
:
1298 ShareFixedAtBuildPcdsSameValue
[key
] = True
1299 FixedAtBuildPcds
[key
] = Pcd
.DefaultValue
1301 if FixedAtBuildPcds
[key
] != Pcd
.DefaultValue
:
1302 ShareFixedAtBuildPcdsSameValue
[key
] = False
1303 for Pcd
in LibAuto
.FixedAtBuildPcds
:
1304 key
= ".".join((Pcd
.TokenSpaceGuidCName
,Pcd
.TokenCName
))
1305 if (Pcd
.TokenCName
,Pcd
.TokenSpaceGuidCName
) not in self
.NonDynamicPcdDict
:
1308 DscPcd
= self
.NonDynamicPcdDict
[(Pcd
.TokenCName
,Pcd
.TokenSpaceGuidCName
)]
1309 if DscPcd
.Type
!= "FixedAtBuild":
1311 if key
in ShareFixedAtBuildPcdsSameValue
and ShareFixedAtBuildPcdsSameValue
[key
]:
1312 LibAuto
.ConstPcd
[key
] = Pcd
.DefaultValue
1314 def CollectVariables(self
, DynamicPcdSet
):
1318 if self
.Workspace
.FdfFile
:
1319 FdDict
= self
.Workspace
.FdfProfile
.FdDict
[GlobalData
.gFdfParser
.CurrentFdName
]
1320 for FdRegion
in FdDict
.RegionList
:
1321 for item
in FdRegion
.RegionDataList
:
1322 if self
.Platform
.VpdToolGuid
.strip() and self
.Platform
.VpdToolGuid
in item
:
1323 VpdRegionSize
= FdRegion
.Size
1324 VpdRegionBase
= FdRegion
.Offset
1328 VariableInfo
= VariableMgr(self
.DscBuildDataObj
._GetDefaultStores
(),self
.DscBuildDataObj
._GetSkuIds
())
1329 VariableInfo
.SetVpdRegionMaxSize(VpdRegionSize
)
1330 VariableInfo
.SetVpdRegionOffset(VpdRegionBase
)
1332 for Pcd
in DynamicPcdSet
:
1333 pcdname
= ".".join((Pcd
.TokenSpaceGuidCName
,Pcd
.TokenCName
))
1334 for SkuName
in Pcd
.SkuInfoList
:
1335 Sku
= Pcd
.SkuInfoList
[SkuName
]
1337 if SkuId
is None or SkuId
== '':
1339 if len(Sku
.VariableName
) > 0:
1340 VariableGuidStructure
= Sku
.VariableGuidValue
1341 VariableGuid
= GuidStructureStringToGuidString(VariableGuidStructure
)
1342 for StorageName
in Sku
.DefaultStoreDict
:
1343 VariableInfo
.append_variable(var_info(Index
,pcdname
,StorageName
,SkuName
, StringToArray(Sku
.VariableName
),VariableGuid
, Sku
.VariableOffset
, Sku
.VariableAttribute
, Sku
.HiiDefaultValue
,Sku
.DefaultStoreDict
[StorageName
],Pcd
.DatumType
))
1347 def UpdateNVStoreMaxSize(self
,OrgVpdFile
):
1348 if self
.VariableInfo
:
1349 VpdMapFilePath
= os
.path
.join(self
.BuildDir
, "FV", "%s.map" % self
.Platform
.VpdToolGuid
)
1350 PcdNvStoreDfBuffer
= [item
for item
in self
._DynamicPcdList
if item
.TokenCName
== "PcdNvStoreDefaultValueBuffer" and item
.TokenSpaceGuidCName
== "gEfiMdeModulePkgTokenSpaceGuid"]
1352 if PcdNvStoreDfBuffer
:
1353 if os
.path
.exists(VpdMapFilePath
):
1354 OrgVpdFile
.Read(VpdMapFilePath
)
1355 PcdItems
= OrgVpdFile
.GetOffset(PcdNvStoreDfBuffer
[0])
1356 NvStoreOffset
= PcdItems
.values()[0].strip() if PcdItems
else '0'
1358 EdkLogger
.error("build", FILE_READ_FAILURE
, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath
)
1360 NvStoreOffset
= int(NvStoreOffset
,16) if NvStoreOffset
.upper().startswith("0X") else int(NvStoreOffset
)
1361 default_skuobj
= PcdNvStoreDfBuffer
[0].SkuInfoList
.get("DEFAULT")
1362 maxsize
= self
.VariableInfo
.VpdRegionSize
- NvStoreOffset
if self
.VariableInfo
.VpdRegionSize
else len(default_skuobj
.DefaultValue
.split(","))
1363 var_data
= self
.VariableInfo
.PatchNVStoreDefaultMaxSize(maxsize
)
1365 if var_data
and default_skuobj
:
1366 default_skuobj
.DefaultValue
= var_data
1367 PcdNvStoreDfBuffer
[0].DefaultValue
= var_data
1368 PcdNvStoreDfBuffer
[0].SkuInfoList
.clear()
1369 PcdNvStoreDfBuffer
[0].SkuInfoList
['DEFAULT'] = default_skuobj
1370 PcdNvStoreDfBuffer
[0].MaxDatumSize
= str(len(default_skuobj
.DefaultValue
.split(",")))
1374 ## Collect dynamic PCDs
1376 # Gather dynamic PCDs list from each module and their settings from platform
1377 # This interface should be invoked explicitly when platform action is created.
1379 def CollectPlatformDynamicPcds(self
):
1381 for key
in self
.Platform
.Pcds
:
1382 for SinglePcd
in GlobalData
.MixedPcd
:
1383 if (self
.Platform
.Pcds
[key
].TokenCName
, self
.Platform
.Pcds
[key
].TokenSpaceGuidCName
) == SinglePcd
:
1384 for item
in GlobalData
.MixedPcd
[SinglePcd
]:
1385 Pcd_Type
= item
[0].split('_')[-1]
1386 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 \
1387 (Pcd_Type
== TAB_PCDS_DYNAMIC
and self
.Platform
.Pcds
[key
].Type
in GenC
.gDynamicPcd
):
1388 Value
= self
.Platform
.Pcds
[key
]
1389 Value
.TokenCName
= self
.Platform
.Pcds
[key
].TokenCName
+ '_' + Pcd_Type
1391 newkey
= (Value
.TokenCName
, key
[1])
1393 newkey
= (Value
.TokenCName
, key
[1], key
[2])
1394 del self
.Platform
.Pcds
[key
]
1395 self
.Platform
.Pcds
[newkey
] = Value
1403 # for gathering error information
1404 NoDatumTypePcdList
= set()
1406 self
._GuidValue
= {}
1408 for InfName
in self
._AsBuildInfList
:
1409 InfName
= mws
.join(self
.WorkspaceDir
, InfName
)
1410 FdfModuleList
.append(os
.path
.normpath(InfName
))
1411 for F
in self
.Platform
.Modules
.keys():
1412 M
= ModuleAutoGen(self
.Workspace
, F
, self
.BuildTarget
, self
.ToolChain
, self
.Arch
, self
.MetaFile
)
1413 #GuidValue.update(M.Guids)
1415 self
.Platform
.Modules
[F
].M
= M
1417 for PcdFromModule
in M
.ModulePcdList
+ M
.LibraryPcdList
:
1418 # make sure that the "VOID*" kind of datum has MaxDatumSize set
1419 if PcdFromModule
.DatumType
== "VOID*" and PcdFromModule
.MaxDatumSize
in [None, '']:
1420 NoDatumTypePcdList
.add("%s.%s [%s]" % (PcdFromModule
.TokenSpaceGuidCName
, PcdFromModule
.TokenCName
, F
))
1422 # Check the PCD from Binary INF or Source INF
1423 if M
.IsBinaryModule
== True:
1424 PcdFromModule
.IsFromBinaryInf
= True
1426 # Check the PCD from DSC or not
1427 if (PcdFromModule
.TokenCName
, PcdFromModule
.TokenSpaceGuidCName
) in self
.Platform
.Pcds
.keys():
1428 PcdFromModule
.IsFromDsc
= True
1430 PcdFromModule
.IsFromDsc
= False
1431 if PcdFromModule
.Type
in GenC
.gDynamicPcd
or PcdFromModule
.Type
in GenC
.gDynamicExPcd
:
1432 if F
.Path
not in FdfModuleList
:
1433 # If one of the Source built modules listed in the DSC is not listed
1434 # in FDF modules, and the INF lists a PCD can only use the PcdsDynamic
1435 # access method (it is only listed in the DEC file that declares the
1436 # PCD as PcdsDynamic), then build tool will report warning message
1437 # notify the PI that they are attempting to build a module that must
1438 # be included in a flash image in order to be functional. These Dynamic
1439 # PCD will not be added into the Database unless it is used by other
1440 # modules that are included in the FDF file.
1441 if PcdFromModule
.Type
in GenC
.gDynamicPcd
and \
1442 PcdFromModule
.IsFromBinaryInf
== False:
1443 # Print warning message to let the developer make a determine.
1444 if PcdFromModule
not in PcdNotInDb
:
1445 PcdNotInDb
.append(PcdFromModule
)
1447 # If one of the Source built modules listed in the DSC is not listed in
1448 # FDF modules, and the INF lists a PCD can only use the PcdsDynamicEx
1449 # access method (it is only listed in the DEC file that declares the
1450 # PCD as PcdsDynamicEx), then DO NOT break the build; DO NOT add the
1451 # PCD to the Platform's PCD Database.
1452 if PcdFromModule
.Type
in GenC
.gDynamicExPcd
:
1453 if PcdFromModule
not in PcdNotInDb
:
1454 PcdNotInDb
.append(PcdFromModule
)
1457 # If a dynamic PCD used by a PEM module/PEI module & DXE module,
1458 # it should be stored in Pcd PEI database, If a dynamic only
1459 # used by DXE module, it should be stored in DXE PCD database.
1460 # The default Phase is DXE
1462 if M
.ModuleType
in ["PEIM", "PEI_CORE"]:
1463 PcdFromModule
.Phase
= "PEI"
1464 if PcdFromModule
not in self
._DynaPcdList
_:
1465 self
._DynaPcdList
_.append(PcdFromModule
)
1466 elif PcdFromModule
.Phase
== 'PEI':
1467 # overwrite any the same PCD existing, if Phase is PEI
1468 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1469 self
._DynaPcdList
_[Index
] = PcdFromModule
1470 elif PcdFromModule
not in self
._NonDynaPcdList
_:
1471 self
._NonDynaPcdList
_.append(PcdFromModule
)
1472 elif PcdFromModule
in self
._NonDynaPcdList
_ and PcdFromModule
.IsFromBinaryInf
== True:
1473 Index
= self
._NonDynaPcdList
_.index(PcdFromModule
)
1474 if self
._NonDynaPcdList
_[Index
].IsFromBinaryInf
== False:
1475 #The PCD from Binary INF will override the same one from source INF
1476 self
._NonDynaPcdList
_.remove (self
._NonDynaPcdList
_[Index
])
1477 PcdFromModule
.Pending
= False
1478 self
._NonDynaPcdList
_.append (PcdFromModule
)
1479 # Parse the DynamicEx PCD from the AsBuild INF module list of FDF.
1481 for ModuleInf
in self
.Platform
.Modules
.keys():
1482 DscModuleList
.append (os
.path
.normpath(ModuleInf
.Path
))
1483 # add the PCD from modules that listed in FDF but not in DSC to Database
1484 for InfName
in FdfModuleList
:
1485 if InfName
not in DscModuleList
:
1486 InfClass
= PathClass(InfName
)
1487 M
= self
.BuildDatabase
[InfClass
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1488 # If a module INF in FDF but not in current arch's DSC module list, it must be module (either binary or source)
1489 # for different Arch. PCDs in source module for different Arch is already added before, so skip the source module here.
1490 # For binary module, if in current arch, we need to list the PCDs into database.
1491 if not M
.IsSupportedArch
:
1493 # Override the module PCD setting by platform setting
1494 ModulePcdList
= self
.ApplyPcdSetting(M
, M
.Pcds
)
1495 for PcdFromModule
in ModulePcdList
:
1496 PcdFromModule
.IsFromBinaryInf
= True
1497 PcdFromModule
.IsFromDsc
= False
1498 # Only allow the DynamicEx and Patchable PCD in AsBuild INF
1499 if PcdFromModule
.Type
not in GenC
.gDynamicExPcd
and PcdFromModule
.Type
not in TAB_PCDS_PATCHABLE_IN_MODULE
:
1500 EdkLogger
.error("build", AUTOGEN_ERROR
, "PCD setting error",
1502 ExtraData
="\n\tExisted %s PCD %s in:\n\t\t%s\n"
1503 % (PcdFromModule
.Type
, PcdFromModule
.TokenCName
, InfName
))
1504 # make sure that the "VOID*" kind of datum has MaxDatumSize set
1505 if PcdFromModule
.DatumType
== "VOID*" and PcdFromModule
.MaxDatumSize
in [None, '']:
1506 NoDatumTypePcdList
.add("%s.%s [%s]" % (PcdFromModule
.TokenSpaceGuidCName
, PcdFromModule
.TokenCName
, InfName
))
1507 if M
.ModuleType
in ["PEIM", "PEI_CORE"]:
1508 PcdFromModule
.Phase
= "PEI"
1509 if PcdFromModule
not in self
._DynaPcdList
_ and PcdFromModule
.Type
in GenC
.gDynamicExPcd
:
1510 self
._DynaPcdList
_.append(PcdFromModule
)
1511 elif PcdFromModule
not in self
._NonDynaPcdList
_ and PcdFromModule
.Type
in TAB_PCDS_PATCHABLE_IN_MODULE
:
1512 self
._NonDynaPcdList
_.append(PcdFromModule
)
1513 if PcdFromModule
in self
._DynaPcdList
_ and PcdFromModule
.Phase
== 'PEI' and PcdFromModule
.Type
in GenC
.gDynamicExPcd
:
1514 # Overwrite the phase of any the same PCD existing, if Phase is PEI.
1515 # It is to solve the case that a dynamic PCD used by a PEM module/PEI
1516 # module & DXE module at a same time.
1517 # Overwrite the type of the PCDs in source INF by the type of AsBuild
1518 # INF file as DynamicEx.
1519 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1520 self
._DynaPcdList
_[Index
].Phase
= PcdFromModule
.Phase
1521 self
._DynaPcdList
_[Index
].Type
= PcdFromModule
.Type
1522 for PcdFromModule
in self
._NonDynaPcdList
_:
1523 # If a PCD is not listed in the DSC file, but binary INF files used by
1524 # this platform all (that use this PCD) list the PCD in a [PatchPcds]
1525 # section, AND all source INF files used by this platform the build
1526 # that use the PCD list the PCD in either a [Pcds] or [PatchPcds]
1527 # section, then the tools must NOT add the PCD to the Platform's PCD
1528 # Database; the build must assign the access method for this PCD as
1529 # PcdsPatchableInModule.
1530 if PcdFromModule
not in self
._DynaPcdList
_:
1532 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1533 if PcdFromModule
.IsFromDsc
== False and \
1534 PcdFromModule
.Type
in TAB_PCDS_PATCHABLE_IN_MODULE
and \
1535 PcdFromModule
.IsFromBinaryInf
== True and \
1536 self
._DynaPcdList
_[Index
].IsFromBinaryInf
== False:
1537 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1538 self
._DynaPcdList
_.remove (self
._DynaPcdList
_[Index
])
1540 # print out error information and break the build, if error found
1541 if len(NoDatumTypePcdList
) > 0:
1542 NoDatumTypePcdListString
= "\n\t\t".join(NoDatumTypePcdList
)
1543 EdkLogger
.error("build", AUTOGEN_ERROR
, "PCD setting error",
1545 ExtraData
="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"
1546 % NoDatumTypePcdListString
)
1547 self
._NonDynamicPcdList
= self
._NonDynaPcdList
_
1548 self
._DynamicPcdList
= self
._DynaPcdList
_
1550 # Sort dynamic PCD list to:
1551 # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should
1552 # try to be put header of dynamicd List
1553 # 2) If PCD is HII type, the PCD item should be put after unicode type PCD
1555 # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.
1557 UnicodePcdArray
= set()
1559 OtherPcdArray
= set()
1561 VpdFile
= VpdInfoFile
.VpdInfoFile()
1562 NeedProcessVpdMapFile
= False
1564 for pcd
in self
.Platform
.Pcds
.keys():
1565 if pcd
not in self
._PlatformPcds
.keys():
1566 self
._PlatformPcds
[pcd
] = self
.Platform
.Pcds
[pcd
]
1568 for item
in self
._PlatformPcds
:
1569 if self
._PlatformPcds
[item
].DatumType
and self
._PlatformPcds
[item
].DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
1570 self
._PlatformPcds
[item
].DatumType
= "VOID*"
1572 if (self
.Workspace
.ArchList
[-1] == self
.Arch
):
1573 for Pcd
in self
._DynamicPcdList
:
1574 # just pick the a value to determine whether is unicode string type
1575 Sku
= Pcd
.SkuInfoList
[Pcd
.SkuInfoList
.keys()[0]]
1576 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1578 if Pcd
.DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
1579 Pcd
.DatumType
= "VOID*"
1581 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
1582 # if found HII type PCD then insert to right of UnicodeIndex
1583 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
1584 VpdPcdDict
[(Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
)] = Pcd
1586 #Collect DynamicHii PCD values and assign it to DynamicExVpd PCD gEfiMdeModulePkgTokenSpaceGuid.PcdNvStoreDefaultValueBuffer
1587 PcdNvStoreDfBuffer
= VpdPcdDict
.get(("PcdNvStoreDefaultValueBuffer","gEfiMdeModulePkgTokenSpaceGuid"))
1588 if PcdNvStoreDfBuffer
:
1589 self
.VariableInfo
= self
.CollectVariables(self
._DynamicPcdList
)
1590 vardump
= self
.VariableInfo
.dump()
1592 PcdNvStoreDfBuffer
.DefaultValue
= vardump
1593 for skuname
in PcdNvStoreDfBuffer
.SkuInfoList
:
1594 PcdNvStoreDfBuffer
.SkuInfoList
[skuname
].DefaultValue
= vardump
1595 PcdNvStoreDfBuffer
.MaxDatumSize
= str(len(vardump
.split(",")))
1597 PlatformPcds
= self
._PlatformPcds
.keys()
1600 # Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.
1603 for PcdKey
in PlatformPcds
:
1604 Pcd
= self
._PlatformPcds
[PcdKey
]
1605 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
] and \
1606 PcdKey
in VpdPcdDict
:
1607 Pcd
= VpdPcdDict
[PcdKey
]
1609 DefaultSku
= Pcd
.SkuInfoList
.get('DEFAULT')
1611 PcdValue
= DefaultSku
.DefaultValue
1612 if PcdValue
not in SkuValueMap
:
1613 SkuValueMap
[PcdValue
] = []
1614 VpdFile
.Add(Pcd
, 'DEFAULT',DefaultSku
.VpdOffset
)
1615 SkuValueMap
[PcdValue
].append(DefaultSku
)
1617 for (SkuName
,Sku
) in Pcd
.SkuInfoList
.items():
1618 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1619 PcdValue
= Sku
.DefaultValue
1621 PcdValue
= Pcd
.DefaultValue
1622 if Sku
.VpdOffset
!= '*':
1623 if PcdValue
.startswith("{"):
1625 elif PcdValue
.startswith("L"):
1630 VpdOffset
= int(Sku
.VpdOffset
)
1633 VpdOffset
= int(Sku
.VpdOffset
, 16)
1635 EdkLogger
.error("build", FORMAT_INVALID
, "Invalid offset value %s for PCD %s.%s." % (Sku
.VpdOffset
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
1636 if VpdOffset
% Alignment
!= 0:
1637 if PcdValue
.startswith("{"):
1638 EdkLogger
.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
), File
=self
.MetaFile
)
1640 EdkLogger
.error("build", FORMAT_INVALID
, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
, Alignment
))
1641 if PcdValue
not in SkuValueMap
:
1642 SkuValueMap
[PcdValue
] = []
1643 VpdFile
.Add(Pcd
, SkuName
,Sku
.VpdOffset
)
1644 SkuValueMap
[PcdValue
].append(Sku
)
1645 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
1646 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== "*":
1647 NeedProcessVpdMapFile
= True
1648 if self
.Platform
.VpdToolGuid
is None or self
.Platform
.VpdToolGuid
== '':
1649 EdkLogger
.error("Build", FILE_NOT_FOUND
, \
1650 "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.")
1652 VpdSkuMap
[PcdKey
] = SkuValueMap
1654 # Fix the PCDs define in VPD PCD section that never referenced by module.
1655 # An example is PCD for signature usage.
1657 for DscPcd
in PlatformPcds
:
1658 DscPcdEntry
= self
._PlatformPcds
[DscPcd
]
1659 if DscPcdEntry
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
1660 if not (self
.Platform
.VpdToolGuid
is None or self
.Platform
.VpdToolGuid
== ''):
1662 for VpdPcd
in VpdFile
._VpdArray
.keys():
1663 # This PCD has been referenced by module
1664 if (VpdPcd
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
1665 (VpdPcd
.TokenCName
== DscPcdEntry
.TokenCName
):
1668 # Not found, it should be signature
1670 # just pick the a value to determine whether is unicode string type
1672 SkuObjList
= DscPcdEntry
.SkuInfoList
.items()
1673 DefaultSku
= DscPcdEntry
.SkuInfoList
.get('DEFAULT')
1675 defaultindex
= SkuObjList
.index(('DEFAULT',DefaultSku
))
1676 SkuObjList
[0],SkuObjList
[defaultindex
] = SkuObjList
[defaultindex
],SkuObjList
[0]
1677 for (SkuName
,Sku
) in SkuObjList
:
1678 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1680 # Need to iterate DEC pcd information to get the value & datumtype
1681 for eachDec
in self
.PackageList
:
1682 for DecPcd
in eachDec
.Pcds
:
1683 DecPcdEntry
= eachDec
.Pcds
[DecPcd
]
1684 if (DecPcdEntry
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
1685 (DecPcdEntry
.TokenCName
== DscPcdEntry
.TokenCName
):
1686 # Print warning message to let the developer make a determine.
1687 EdkLogger
.warn("build", "Unreferenced vpd pcd used!",
1688 File
=self
.MetaFile
, \
1689 ExtraData
= "PCD: %s.%s used in the DSC file %s is unreferenced." \
1690 %(DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
, self
.Platform
.MetaFile
.Path
))
1692 DscPcdEntry
.DatumType
= DecPcdEntry
.DatumType
1693 DscPcdEntry
.DefaultValue
= DecPcdEntry
.DefaultValue
1694 DscPcdEntry
.TokenValue
= DecPcdEntry
.TokenValue
1695 DscPcdEntry
.TokenSpaceGuidValue
= eachDec
.Guids
[DecPcdEntry
.TokenSpaceGuidCName
]
1696 # Only fix the value while no value provided in DSC file.
1697 if (Sku
.DefaultValue
== "" or Sku
.DefaultValue
==None):
1698 DscPcdEntry
.SkuInfoList
[DscPcdEntry
.SkuInfoList
.keys()[0]].DefaultValue
= DecPcdEntry
.DefaultValue
1700 if DscPcdEntry
not in self
._DynamicPcdList
:
1701 self
._DynamicPcdList
.append(DscPcdEntry
)
1702 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1703 PcdValue
= Sku
.DefaultValue
1705 PcdValue
= DscPcdEntry
.DefaultValue
1706 if Sku
.VpdOffset
!= '*':
1707 if PcdValue
.startswith("{"):
1709 elif PcdValue
.startswith("L"):
1714 VpdOffset
= int(Sku
.VpdOffset
)
1717 VpdOffset
= int(Sku
.VpdOffset
, 16)
1719 EdkLogger
.error("build", FORMAT_INVALID
, "Invalid offset value %s for PCD %s.%s." % (Sku
.VpdOffset
, DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
))
1720 if VpdOffset
% Alignment
!= 0:
1721 if PcdValue
.startswith("{"):
1722 EdkLogger
.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
), File
=self
.MetaFile
)
1724 EdkLogger
.error("build", FORMAT_INVALID
, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
, Alignment
))
1725 if PcdValue
not in SkuValueMap
:
1726 SkuValueMap
[PcdValue
] = []
1727 VpdFile
.Add(DscPcdEntry
, SkuName
,Sku
.VpdOffset
)
1728 SkuValueMap
[PcdValue
].append(Sku
)
1729 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== "*":
1730 NeedProcessVpdMapFile
= True
1731 if DscPcdEntry
.DatumType
== 'VOID*' and PcdValue
.startswith("L"):
1732 UnicodePcdArray
.add(DscPcdEntry
)
1733 elif len(Sku
.VariableName
) > 0:
1734 HiiPcdArray
.add(DscPcdEntry
)
1736 OtherPcdArray
.add(DscPcdEntry
)
1738 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
1739 VpdSkuMap
[DscPcd
] = SkuValueMap
1740 if (self
.Platform
.FlashDefinition
is None or self
.Platform
.FlashDefinition
== '') and \
1741 VpdFile
.GetCount() != 0:
1742 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
,
1743 "Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD." % str(self
.Platform
.MetaFile
))
1745 if VpdFile
.GetCount() != 0:
1747 self
.FixVpdOffset(VpdFile
)
1749 self
.FixVpdOffset(self
.UpdateNVStoreMaxSize(VpdFile
))
1751 # Process VPD map file generated by third party BPDG tool
1752 if NeedProcessVpdMapFile
:
1753 VpdMapFilePath
= os
.path
.join(self
.BuildDir
, "FV", "%s.map" % self
.Platform
.VpdToolGuid
)
1754 if os
.path
.exists(VpdMapFilePath
):
1755 VpdFile
.Read(VpdMapFilePath
)
1758 for pcd
in VpdSkuMap
:
1759 vpdinfo
= VpdFile
.GetVpdInfo(pcd
)
1761 # just pick the a value to determine whether is unicode string type
1763 for pcdvalue
in VpdSkuMap
[pcd
]:
1764 for sku
in VpdSkuMap
[pcd
][pcdvalue
]:
1765 for item
in vpdinfo
:
1766 if item
[2] == pcdvalue
:
1767 sku
.VpdOffset
= item
[1]
1769 EdkLogger
.error("build", FILE_READ_FAILURE
, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath
)
1771 # Delete the DynamicPcdList At the last time enter into this function
1772 for Pcd
in self
._DynamicPcdList
:
1773 # just pick the a value to determine whether is unicode string type
1774 Sku
= Pcd
.SkuInfoList
[Pcd
.SkuInfoList
.keys()[0]]
1775 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1777 if Pcd
.DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
1778 Pcd
.DatumType
= "VOID*"
1780 PcdValue
= Sku
.DefaultValue
1781 if Pcd
.DatumType
== 'VOID*' and PcdValue
.startswith("L"):
1782 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
1783 UnicodePcdArray
.add(Pcd
)
1784 elif len(Sku
.VariableName
) > 0:
1785 # if found HII type PCD then insert to right of UnicodeIndex
1786 HiiPcdArray
.add(Pcd
)
1788 OtherPcdArray
.add(Pcd
)
1789 del self
._DynamicPcdList
[:]
1790 self
._DynamicPcdList
.extend(list(UnicodePcdArray
))
1791 self
._DynamicPcdList
.extend(list(HiiPcdArray
))
1792 self
._DynamicPcdList
.extend(list(OtherPcdArray
))
1793 allskuset
= [(SkuName
,Sku
.SkuId
) for pcd
in self
._DynamicPcdList
for (SkuName
,Sku
) in pcd
.SkuInfoList
.items()]
1794 for pcd
in self
._DynamicPcdList
:
1795 if len(pcd
.SkuInfoList
) == 1:
1796 for (SkuName
,SkuId
) in allskuset
:
1797 if type(SkuId
) in (str,unicode) and eval(SkuId
) == 0 or SkuId
== 0:
1799 pcd
.SkuInfoList
[SkuName
] = copy
.deepcopy(pcd
.SkuInfoList
['DEFAULT'])
1800 pcd
.SkuInfoList
[SkuName
].SkuId
= SkuId
1801 self
.AllPcdList
= self
._NonDynamicPcdList
+ self
._DynamicPcdList
1803 def FixVpdOffset(self
,VpdFile
):
1804 FvPath
= os
.path
.join(self
.BuildDir
, "FV")
1805 if not os
.path
.exists(FvPath
):
1809 EdkLogger
.error("build", FILE_WRITE_FAILURE
, "Fail to create FV folder under %s" % self
.BuildDir
)
1811 VpdFilePath
= os
.path
.join(FvPath
, "%s.txt" % self
.Platform
.VpdToolGuid
)
1813 if VpdFile
.Write(VpdFilePath
):
1814 # retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.
1816 for ToolDef
in self
.ToolDefinition
.values():
1817 if ToolDef
.has_key("GUID") and ToolDef
["GUID"] == self
.Platform
.VpdToolGuid
:
1818 if not ToolDef
.has_key("PATH"):
1819 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
, "PATH attribute was not provided for BPDG guid tool %s in tools_def.txt" % self
.Platform
.VpdToolGuid
)
1820 BPDGToolName
= ToolDef
["PATH"]
1822 # Call third party GUID BPDG tool.
1823 if BPDGToolName
is not None:
1824 VpdInfoFile
.CallExtenalBPDGTool(BPDGToolName
, VpdFilePath
)
1826 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.")
1828 ## Return the platform build data object
1829 def _GetPlatform(self
):
1830 if self
._Platform
is None:
1831 self
._Platform
= self
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1832 return self
._Platform
1834 ## Return platform name
1836 return self
.Platform
.PlatformName
1838 ## Return the meta file GUID
1840 return self
.Platform
.Guid
1842 ## Return the platform version
1843 def _GetVersion(self
):
1844 return self
.Platform
.Version
1846 ## Return the FDF file name
1847 def _GetFdfFile(self
):
1848 if self
._FdfFile
is None:
1849 if self
.Workspace
.FdfFile
!= "":
1850 self
._FdfFile
= mws
.join(self
.WorkspaceDir
, self
.Workspace
.FdfFile
)
1853 return self
._FdfFile
1855 ## Return the build output directory platform specifies
1856 def _GetOutputDir(self
):
1857 return self
.Platform
.OutputDirectory
1859 ## Return the directory to store all intermediate and final files built
1860 def _GetBuildDir(self
):
1861 if self
._BuildDir
is None:
1862 if os
.path
.isabs(self
.OutputDir
):
1863 self
._BuildDir
= path
.join(
1864 path
.abspath(self
.OutputDir
),
1865 self
.BuildTarget
+ "_" + self
.ToolChain
,
1868 self
._BuildDir
= path
.join(
1871 self
.BuildTarget
+ "_" + self
.ToolChain
,
1873 GlobalData
.gBuildDirectory
= self
._BuildDir
1874 return self
._BuildDir
1876 ## Return directory of platform makefile
1878 # @retval string Makefile directory
1880 def _GetMakeFileDir(self
):
1881 if self
._MakeFileDir
is None:
1882 self
._MakeFileDir
= path
.join(self
.BuildDir
, self
.Arch
)
1883 return self
._MakeFileDir
1885 ## Return build command string
1887 # @retval string Build command string
1889 def _GetBuildCommand(self
):
1890 if self
._BuildCommand
is None:
1891 self
._BuildCommand
= []
1892 if "MAKE" in self
.ToolDefinition
and "PATH" in self
.ToolDefinition
["MAKE"]:
1893 self
._BuildCommand
+= SplitOption(self
.ToolDefinition
["MAKE"]["PATH"])
1894 if "FLAGS" in self
.ToolDefinition
["MAKE"]:
1895 NewOption
= self
.ToolDefinition
["MAKE"]["FLAGS"].strip()
1897 self
._BuildCommand
+= SplitOption(NewOption
)
1898 if "MAKE" in self
.EdkIIBuildOption
:
1899 if "FLAGS" in self
.EdkIIBuildOption
["MAKE"]:
1900 Flags
= self
.EdkIIBuildOption
["MAKE"]["FLAGS"]
1901 if Flags
.startswith('='):
1902 self
._BuildCommand
= [self
._BuildCommand
[0]] + [Flags
[1:]]
1904 self
._BuildCommand
+= [Flags
]
1905 return self
._BuildCommand
1907 ## Get tool chain definition
1909 # Get each tool defition for given tool chain from tools_def.txt and platform
1911 def _GetToolDefinition(self
):
1912 if self
._ToolDefinitions
is None:
1913 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDictionary
1914 if TAB_TOD_DEFINES_COMMAND_TYPE
not in self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
:
1915 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
, "No tools found in configuration",
1916 ExtraData
="[%s]" % self
.MetaFile
)
1917 self
._ToolDefinitions
= {}
1919 for Def
in ToolDefinition
:
1920 Target
, Tag
, Arch
, Tool
, Attr
= Def
.split("_")
1921 if Target
!= self
.BuildTarget
or Tag
!= self
.ToolChain
or Arch
!= self
.Arch
:
1924 Value
= ToolDefinition
[Def
]
1925 # don't record the DLL
1927 DllPathList
.add(Value
)
1930 if Tool
not in self
._ToolDefinitions
:
1931 self
._ToolDefinitions
[Tool
] = {}
1932 self
._ToolDefinitions
[Tool
][Attr
] = Value
1936 if GlobalData
.gOptions
.SilentMode
and "MAKE" in self
._ToolDefinitions
:
1937 if "FLAGS" not in self
._ToolDefinitions
["MAKE"]:
1938 self
._ToolDefinitions
["MAKE"]["FLAGS"] = ""
1939 self
._ToolDefinitions
["MAKE"]["FLAGS"] += " -s"
1941 for Tool
in self
._ToolDefinitions
:
1942 for Attr
in self
._ToolDefinitions
[Tool
]:
1943 Value
= self
._ToolDefinitions
[Tool
][Attr
]
1944 if Tool
in self
.BuildOption
and Attr
in self
.BuildOption
[Tool
]:
1945 # check if override is indicated
1946 if self
.BuildOption
[Tool
][Attr
].startswith('='):
1947 Value
= self
.BuildOption
[Tool
][Attr
][1:]
1950 Value
+= " " + self
.BuildOption
[Tool
][Attr
]
1952 Value
= self
.BuildOption
[Tool
][Attr
]
1955 # Don't put MAKE definition in the file
1959 ToolsDef
+= "%s = %s\n" % (Tool
, Value
)
1961 # Don't put MAKE definition in the file
1966 ToolsDef
+= "%s_%s = %s\n" % (Tool
, Attr
, Value
)
1969 SaveFileOnChange(self
.ToolDefinitionFile
, ToolsDef
)
1970 for DllPath
in DllPathList
:
1971 os
.environ
["PATH"] = DllPath
+ os
.pathsep
+ os
.environ
["PATH"]
1972 os
.environ
["MAKE_FLAGS"] = MakeFlags
1974 return self
._ToolDefinitions
1976 ## Return the paths of tools
1977 def _GetToolDefFile(self
):
1978 if self
._ToolDefFile
is None:
1979 self
._ToolDefFile
= os
.path
.join(self
.MakeFileDir
, "TOOLS_DEF." + self
.Arch
)
1980 return self
._ToolDefFile
1982 ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
1983 def _GetToolChainFamily(self
):
1984 if self
._ToolChainFamily
is None:
1985 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
1986 if TAB_TOD_DEFINES_FAMILY
not in ToolDefinition \
1987 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_FAMILY
] \
1988 or not ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]:
1989 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1991 self
._ToolChainFamily
= "MSFT"
1993 self
._ToolChainFamily
= ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]
1994 return self
._ToolChainFamily
1996 def _GetBuildRuleFamily(self
):
1997 if self
._BuildRuleFamily
is None:
1998 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
1999 if TAB_TOD_DEFINES_BUILDRULEFAMILY
not in ToolDefinition \
2000 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
] \
2001 or not ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]:
2002 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
2004 self
._BuildRuleFamily
= "MSFT"
2006 self
._BuildRuleFamily
= ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]
2007 return self
._BuildRuleFamily
2009 ## Return the build options specific for all modules in this platform
2010 def _GetBuildOptions(self
):
2011 if self
._BuildOption
is None:
2012 self
._BuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
)
2013 return self
._BuildOption
2015 ## Return the build options specific for EDK modules in this platform
2016 def _GetEdkBuildOptions(self
):
2017 if self
._EdkBuildOption
is None:
2018 self
._EdkBuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDK_NAME
)
2019 return self
._EdkBuildOption
2021 ## Return the build options specific for EDKII modules in this platform
2022 def _GetEdkIIBuildOptions(self
):
2023 if self
._EdkIIBuildOption
is None:
2024 self
._EdkIIBuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDKII_NAME
)
2025 return self
._EdkIIBuildOption
2027 ## Parse build_rule.txt in Conf Directory.
2029 # @retval BuildRule object
2031 def _GetBuildRule(self
):
2032 if self
._BuildRule
is None:
2033 BuildRuleFile
= None
2034 if TAB_TAT_DEFINES_BUILD_RULE_CONF
in self
.Workspace
.TargetTxt
.TargetTxtDictionary
:
2035 BuildRuleFile
= self
.Workspace
.TargetTxt
.TargetTxtDictionary
[TAB_TAT_DEFINES_BUILD_RULE_CONF
]
2036 if BuildRuleFile
in [None, '']:
2037 BuildRuleFile
= gDefaultBuildRuleFile
2038 self
._BuildRule
= BuildRule(BuildRuleFile
)
2039 if self
._BuildRule
._FileVersion
== "":
2040 self
._BuildRule
._FileVersion
= AutoGenReqBuildRuleVerNum
2042 if self
._BuildRule
._FileVersion
< AutoGenReqBuildRuleVerNum
:
2043 # If Build Rule's version is less than the version number required by the tools, halting the build.
2044 EdkLogger
.error("build", AUTOGEN_ERROR
,
2045 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])"\
2046 % (self
._BuildRule
._FileVersion
, AutoGenReqBuildRuleVerNum
))
2048 return self
._BuildRule
2050 ## Summarize the packages used by modules in this platform
2051 def _GetPackageList(self
):
2052 if self
._PackageList
is None:
2053 self
._PackageList
= set()
2054 for La
in self
.LibraryAutoGenList
:
2055 self
._PackageList
.update(La
.DependentPackageList
)
2056 for Ma
in self
.ModuleAutoGenList
:
2057 self
._PackageList
.update(Ma
.DependentPackageList
)
2058 #Collect package set information from INF of FDF
2060 for ModuleFile
in self
._AsBuildModuleList
:
2061 if ModuleFile
in self
.Platform
.Modules
:
2063 ModuleData
= self
.BuildDatabase
[ModuleFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
2064 PkgSet
.update(ModuleData
.Packages
)
2065 self
._PackageList
= list(self
._PackageList
) + list (PkgSet
)
2066 return self
._PackageList
2068 def _GetNonDynamicPcdDict(self
):
2069 if self
._NonDynamicPcdDict
:
2070 return self
._NonDynamicPcdDict
2071 for Pcd
in self
.NonDynamicPcdList
:
2072 self
._NonDynamicPcdDict
[(Pcd
.TokenCName
,Pcd
.TokenSpaceGuidCName
)] = Pcd
2073 return self
._NonDynamicPcdDict
2075 ## Get list of non-dynamic PCDs
2076 def _GetNonDynamicPcdList(self
):
2077 if self
._NonDynamicPcdList
is None:
2078 self
.CollectPlatformDynamicPcds()
2079 return self
._NonDynamicPcdList
2081 ## Get list of dynamic PCDs
2082 def _GetDynamicPcdList(self
):
2083 if self
._DynamicPcdList
is None:
2084 self
.CollectPlatformDynamicPcds()
2085 return self
._DynamicPcdList
2087 ## Generate Token Number for all PCD
2088 def _GetPcdTokenNumbers(self
):
2089 if self
._PcdTokenNumber
is None:
2090 self
._PcdTokenNumber
= OrderedDict()
2093 # Make the Dynamic and DynamicEx PCD use within different TokenNumber area.
2097 # TokenNumber 0 ~ 10
2099 # TokeNumber 11 ~ 20
2101 for Pcd
in self
.DynamicPcdList
:
2102 if Pcd
.Phase
== "PEI":
2103 if Pcd
.Type
in ["Dynamic", "DynamicDefault", "DynamicVpd", "DynamicHii"]:
2104 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2105 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2108 for Pcd
in self
.DynamicPcdList
:
2109 if Pcd
.Phase
== "PEI":
2110 if Pcd
.Type
in ["DynamicEx", "DynamicExDefault", "DynamicExVpd", "DynamicExHii"]:
2111 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2112 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2115 for Pcd
in self
.DynamicPcdList
:
2116 if Pcd
.Phase
== "DXE":
2117 if Pcd
.Type
in ["Dynamic", "DynamicDefault", "DynamicVpd", "DynamicHii"]:
2118 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2119 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2122 for Pcd
in self
.DynamicPcdList
:
2123 if Pcd
.Phase
== "DXE":
2124 if Pcd
.Type
in ["DynamicEx", "DynamicExDefault", "DynamicExVpd", "DynamicExHii"]:
2125 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2126 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2129 for Pcd
in self
.NonDynamicPcdList
:
2130 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2132 return self
._PcdTokenNumber
2134 ## Summarize ModuleAutoGen objects of all modules/libraries to be built for this platform
2135 def _GetAutoGenObjectList(self
):
2136 self
._ModuleAutoGenList
= []
2137 self
._LibraryAutoGenList
= []
2138 for ModuleFile
in self
.Platform
.Modules
:
2147 if Ma
not in self
._ModuleAutoGenList
:
2148 self
._ModuleAutoGenList
.append(Ma
)
2149 for La
in Ma
.LibraryAutoGenList
:
2150 if La
not in self
._LibraryAutoGenList
:
2151 self
._LibraryAutoGenList
.append(La
)
2152 if Ma
not in La
._ReferenceModules
:
2153 La
._ReferenceModules
.append(Ma
)
2155 ## Summarize ModuleAutoGen objects of all modules to be built for this platform
2156 def _GetModuleAutoGenList(self
):
2157 if self
._ModuleAutoGenList
is None:
2158 self
._GetAutoGenObjectList
()
2159 return self
._ModuleAutoGenList
2161 ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
2162 def _GetLibraryAutoGenList(self
):
2163 if self
._LibraryAutoGenList
is None:
2164 self
._GetAutoGenObjectList
()
2165 return self
._LibraryAutoGenList
2167 ## Test if a module is supported by the platform
2169 # An error will be raised directly if the module or its arch is not supported
2170 # by the platform or current configuration
2172 def ValidModule(self
, Module
):
2173 return Module
in self
.Platform
.Modules
or Module
in self
.Platform
.LibraryInstances \
2174 or Module
in self
._AsBuildModuleList
2176 ## Resolve the library classes in a module to library instances
2178 # This method will not only resolve library classes but also sort the library
2179 # instances according to the dependency-ship.
2181 # @param Module The module from which the library classes will be resolved
2183 # @retval library_list List of library instances sorted
2185 def ApplyLibraryInstance(self
, Module
):
2186 # Cover the case that the binary INF file is list in the FDF file but not DSC file, return empty list directly
2187 if str(Module
) not in self
.Platform
.Modules
:
2190 ModuleType
= Module
.ModuleType
2192 # for overridding library instances with module specific setting
2193 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
2195 # add forced library instances (specified under LibraryClasses sections)
2197 # If a module has a MODULE_TYPE of USER_DEFINED,
2198 # do not link in NULL library class instances from the global [LibraryClasses.*] sections.
2200 if Module
.ModuleType
!= SUP_MODULE_USER_DEFINED
:
2201 for LibraryClass
in self
.Platform
.LibraryClasses
.GetKeys():
2202 if LibraryClass
.startswith("NULL") and self
.Platform
.LibraryClasses
[LibraryClass
, Module
.ModuleType
]:
2203 Module
.LibraryClasses
[LibraryClass
] = self
.Platform
.LibraryClasses
[LibraryClass
, Module
.ModuleType
]
2205 # add forced library instances (specified in module overrides)
2206 for LibraryClass
in PlatformModule
.LibraryClasses
:
2207 if LibraryClass
.startswith("NULL"):
2208 Module
.LibraryClasses
[LibraryClass
] = PlatformModule
.LibraryClasses
[LibraryClass
]
2211 LibraryConsumerList
= [Module
]
2213 ConsumedByList
= OrderedDict()
2214 LibraryInstance
= OrderedDict()
2216 EdkLogger
.verbose("")
2217 EdkLogger
.verbose("Library instances of module [%s] [%s]:" % (str(Module
), self
.Arch
))
2218 while len(LibraryConsumerList
) > 0:
2219 M
= LibraryConsumerList
.pop()
2220 for LibraryClassName
in M
.LibraryClasses
:
2221 if LibraryClassName
not in LibraryInstance
:
2222 # override library instance for this module
2223 if LibraryClassName
in PlatformModule
.LibraryClasses
:
2224 LibraryPath
= PlatformModule
.LibraryClasses
[LibraryClassName
]
2226 LibraryPath
= self
.Platform
.LibraryClasses
[LibraryClassName
, ModuleType
]
2227 if LibraryPath
is None or LibraryPath
== "":
2228 LibraryPath
= M
.LibraryClasses
[LibraryClassName
]
2229 if LibraryPath
is None or LibraryPath
== "":
2230 EdkLogger
.error("build", RESOURCE_NOT_AVAILABLE
,
2231 "Instance of library class [%s] is not found" % LibraryClassName
,
2233 ExtraData
="in [%s] [%s]\n\tconsumed by module [%s]" % (str(M
), self
.Arch
, str(Module
)))
2235 LibraryModule
= self
.BuildDatabase
[LibraryPath
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
2236 # for those forced library instance (NULL library), add a fake library class
2237 if LibraryClassName
.startswith("NULL"):
2238 LibraryModule
.LibraryClass
.append(LibraryClassObject(LibraryClassName
, [ModuleType
]))
2239 elif LibraryModule
.LibraryClass
is None \
2240 or len(LibraryModule
.LibraryClass
) == 0 \
2241 or (ModuleType
!= 'USER_DEFINED'
2242 and ModuleType
not in LibraryModule
.LibraryClass
[0].SupModList
):
2243 # only USER_DEFINED can link against any library instance despite of its SupModList
2244 EdkLogger
.error("build", OPTION_MISSING
,
2245 "Module type [%s] is not supported by library instance [%s]" \
2246 % (ModuleType
, LibraryPath
), File
=self
.MetaFile
,
2247 ExtraData
="consumed by [%s]" % str(Module
))
2249 LibraryInstance
[LibraryClassName
] = LibraryModule
2250 LibraryConsumerList
.append(LibraryModule
)
2251 EdkLogger
.verbose("\t" + str(LibraryClassName
) + " : " + str(LibraryModule
))
2253 LibraryModule
= LibraryInstance
[LibraryClassName
]
2255 if LibraryModule
is None:
2258 if LibraryModule
.ConstructorList
!= [] and LibraryModule
not in Constructor
:
2259 Constructor
.append(LibraryModule
)
2261 if LibraryModule
not in ConsumedByList
:
2262 ConsumedByList
[LibraryModule
] = []
2263 # don't add current module itself to consumer list
2265 if M
in ConsumedByList
[LibraryModule
]:
2267 ConsumedByList
[LibraryModule
].append(M
)
2269 # Initialize the sorted output list to the empty set
2271 SortedLibraryList
= []
2273 # Q <- Set of all nodes with no incoming edges
2275 LibraryList
= [] #LibraryInstance.values()
2277 for LibraryClassName
in LibraryInstance
:
2278 M
= LibraryInstance
[LibraryClassName
]
2279 LibraryList
.append(M
)
2280 if ConsumedByList
[M
] == []:
2284 # start the DAG algorithm
2288 while Q
== [] and EdgeRemoved
:
2290 # for each node Item with a Constructor
2291 for Item
in LibraryList
:
2292 if Item
not in Constructor
:
2294 # for each Node without a constructor with an edge e from Item to Node
2295 for Node
in ConsumedByList
[Item
]:
2296 if Node
in Constructor
:
2298 # remove edge e from the graph if Node has no constructor
2299 ConsumedByList
[Item
].remove(Node
)
2301 if ConsumedByList
[Item
] == []:
2302 # insert Item into Q
2307 # DAG is done if there's no more incoming edge for all nodes
2311 # remove node from Q
2314 SortedLibraryList
.append(Node
)
2316 # for each node Item with an edge e from Node to Item do
2317 for Item
in LibraryList
:
2318 if Node
not in ConsumedByList
[Item
]:
2320 # remove edge e from the graph
2321 ConsumedByList
[Item
].remove(Node
)
2323 if ConsumedByList
[Item
] != []:
2325 # insert Item into Q, if Item has no other incoming edges
2329 # if any remaining node Item in the graph has a constructor and an incoming edge, then the graph has a cycle
2331 for Item
in LibraryList
:
2332 if ConsumedByList
[Item
] != [] and Item
in Constructor
and len(Constructor
) > 1:
2333 ErrorMessage
= "\tconsumed by " + "\n\tconsumed by ".join([str(L
) for L
in ConsumedByList
[Item
]])
2334 EdkLogger
.error("build", BUILD_ERROR
, 'Library [%s] with constructors has a cycle' % str(Item
),
2335 ExtraData
=ErrorMessage
, File
=self
.MetaFile
)
2336 if Item
not in SortedLibraryList
:
2337 SortedLibraryList
.append(Item
)
2340 # Build the list of constructor and destructir names
2341 # The DAG Topo sort produces the destructor order, so the list of constructors must generated in the reverse order
2343 SortedLibraryList
.reverse()
2344 return SortedLibraryList
2347 ## Override PCD setting (type, value, ...)
2349 # @param ToPcd The PCD to be overrided
2350 # @param FromPcd The PCD overrideing from
2352 def _OverridePcd(self
, ToPcd
, FromPcd
, Module
=""):
2354 # in case there's PCDs coming from FDF file, which have no type given.
2355 # at this point, ToPcd.Type has the type found from dependent
2358 TokenCName
= ToPcd
.TokenCName
2359 for PcdItem
in GlobalData
.MixedPcd
:
2360 if (ToPcd
.TokenCName
, ToPcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
2361 TokenCName
= PcdItem
[0]
2363 if FromPcd
is not None:
2364 if ToPcd
.Pending
and FromPcd
.Type
not in [None, '']:
2365 ToPcd
.Type
= FromPcd
.Type
2366 elif (ToPcd
.Type
not in [None, '']) and (FromPcd
.Type
not in [None, ''])\
2367 and (ToPcd
.Type
!= FromPcd
.Type
) and (ToPcd
.Type
in FromPcd
.Type
):
2368 if ToPcd
.Type
.strip() == "DynamicEx":
2369 ToPcd
.Type
= FromPcd
.Type
2370 elif ToPcd
.Type
not in [None, ''] and FromPcd
.Type
not in [None, ''] \
2371 and ToPcd
.Type
!= FromPcd
.Type
:
2372 EdkLogger
.error("build", OPTION_CONFLICT
, "Mismatched PCD type",
2373 ExtraData
="%s.%s is defined as [%s] in module %s, but as [%s] in platform."\
2374 % (ToPcd
.TokenSpaceGuidCName
, TokenCName
,
2375 ToPcd
.Type
, Module
, FromPcd
.Type
),
2378 if FromPcd
.MaxDatumSize
not in [None, '']:
2379 ToPcd
.MaxDatumSize
= FromPcd
.MaxDatumSize
2380 if FromPcd
.DefaultValue
not in [None, '']:
2381 ToPcd
.DefaultValue
= FromPcd
.DefaultValue
2382 if FromPcd
.TokenValue
not in [None, '']:
2383 ToPcd
.TokenValue
= FromPcd
.TokenValue
2384 if FromPcd
.MaxDatumSize
not in [None, '']:
2385 ToPcd
.MaxDatumSize
= FromPcd
.MaxDatumSize
2386 if FromPcd
.DatumType
not in [None, '']:
2387 ToPcd
.DatumType
= FromPcd
.DatumType
2388 if FromPcd
.SkuInfoList
not in [None, '', []]:
2389 ToPcd
.SkuInfoList
= FromPcd
.SkuInfoList
2390 # Add Flexible PCD format parse
2391 if ToPcd
.DefaultValue
:
2393 ToPcd
.DefaultValue
= ValueExpressionEx(ToPcd
.DefaultValue
, ToPcd
.DatumType
, self
._GuidDict
)(True)
2394 except BadExpression
, Value
:
2395 EdkLogger
.error('Parser', FORMAT_INVALID
, 'PCD [%s.%s] Value "%s", %s' %(ToPcd
.TokenSpaceGuidCName
, ToPcd
.TokenCName
, ToPcd
.DefaultValue
, Value
),
2398 # check the validation of datum
2399 IsValid
, Cause
= CheckPcdDatum(ToPcd
.DatumType
, ToPcd
.DefaultValue
)
2401 EdkLogger
.error('build', FORMAT_INVALID
, Cause
, File
=self
.MetaFile
,
2402 ExtraData
="%s.%s" % (ToPcd
.TokenSpaceGuidCName
, TokenCName
))
2403 ToPcd
.validateranges
= FromPcd
.validateranges
2404 ToPcd
.validlists
= FromPcd
.validlists
2405 ToPcd
.expressions
= FromPcd
.expressions
2407 if FromPcd
is not None and ToPcd
.DatumType
== "VOID*" and ToPcd
.MaxDatumSize
in ['', None]:
2408 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "No MaxDatumSize specified for PCD %s.%s" \
2409 % (ToPcd
.TokenSpaceGuidCName
, TokenCName
))
2410 Value
= ToPcd
.DefaultValue
2411 if Value
in [None, '']:
2412 ToPcd
.MaxDatumSize
= '1'
2413 elif Value
[0] == 'L':
2414 ToPcd
.MaxDatumSize
= str((len(Value
) - 2) * 2)
2415 elif Value
[0] == '{':
2416 ToPcd
.MaxDatumSize
= str(len(Value
.split(',')))
2418 ToPcd
.MaxDatumSize
= str(len(Value
) - 1)
2420 # apply default SKU for dynamic PCDS if specified one is not available
2421 if (ToPcd
.Type
in PCD_DYNAMIC_TYPE_LIST
or ToPcd
.Type
in PCD_DYNAMIC_EX_TYPE_LIST
) \
2422 and ToPcd
.SkuInfoList
in [None, {}, '']:
2423 if self
.Platform
.SkuName
in self
.Platform
.SkuIds
:
2424 SkuName
= self
.Platform
.SkuName
2427 ToPcd
.SkuInfoList
= {
2428 SkuName
: SkuInfoClass(SkuName
, self
.Platform
.SkuIds
[SkuName
][0], '', '', '', '', '', ToPcd
.DefaultValue
)
2431 ## Apply PCD setting defined platform to a module
2433 # @param Module The module from which the PCD setting will be overrided
2435 # @retval PCD_list The list PCDs with settings from platform
2437 def ApplyPcdSetting(self
, Module
, Pcds
):
2438 # for each PCD in module
2439 for Name
, Guid
in Pcds
:
2440 PcdInModule
= Pcds
[Name
, Guid
]
2441 # find out the PCD setting in platform
2442 if (Name
, Guid
) in self
.Platform
.Pcds
:
2443 PcdInPlatform
= self
.Platform
.Pcds
[Name
, Guid
]
2445 PcdInPlatform
= None
2446 # then override the settings if any
2447 self
._OverridePcd
(PcdInModule
, PcdInPlatform
, Module
)
2448 # resolve the VariableGuid value
2449 for SkuId
in PcdInModule
.SkuInfoList
:
2450 Sku
= PcdInModule
.SkuInfoList
[SkuId
]
2451 if Sku
.VariableGuid
== '': continue
2452 Sku
.VariableGuidValue
= GuidValue(Sku
.VariableGuid
, self
.PackageList
, self
.MetaFile
.Path
)
2453 if Sku
.VariableGuidValue
is None:
2454 PackageList
= "\n\t".join([str(P
) for P
in self
.PackageList
])
2457 RESOURCE_NOT_AVAILABLE
,
2458 "Value of GUID [%s] is not found in" % Sku
.VariableGuid
,
2459 ExtraData
=PackageList
+ "\n\t(used with %s.%s from module %s)" \
2460 % (Guid
, Name
, str(Module
)),
2464 # override PCD settings with module specific setting
2465 if Module
in self
.Platform
.Modules
:
2466 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
2467 for Key
in PlatformModule
.Pcds
:
2472 elif Key
in GlobalData
.MixedPcd
:
2473 for PcdItem
in GlobalData
.MixedPcd
[Key
]:
2475 ToPcd
= Pcds
[PcdItem
]
2479 self
._OverridePcd
(ToPcd
, PlatformModule
.Pcds
[Key
], Module
)
2480 # use PCD value to calculate the MaxDatumSize when it is not specified
2481 for Name
, Guid
in Pcds
:
2482 Pcd
= Pcds
[Name
, Guid
]
2483 if Pcd
.DatumType
== "VOID*" and Pcd
.MaxDatumSize
in ['', None]:
2484 Value
= Pcd
.DefaultValue
2485 if Value
in [None, '']:
2486 Pcd
.MaxDatumSize
= '1'
2487 elif Value
[0] == 'L':
2488 Pcd
.MaxDatumSize
= str((len(Value
) - 2) * 2)
2489 elif Value
[0] == '{':
2490 Pcd
.MaxDatumSize
= str(len(Value
.split(',')))
2492 Pcd
.MaxDatumSize
= str(len(Value
) - 1)
2493 return Pcds
.values()
2495 ## Resolve library names to library modules
2497 # (for Edk.x modules)
2499 # @param Module The module from which the library names will be resolved
2501 # @retval library_list The list of library modules
2503 def ResolveLibraryReference(self
, Module
):
2504 EdkLogger
.verbose("")
2505 EdkLogger
.verbose("Library instances of module [%s] [%s]:" % (str(Module
), self
.Arch
))
2506 LibraryConsumerList
= [Module
]
2508 # "CompilerStub" is a must for Edk modules
2509 if Module
.Libraries
:
2510 Module
.Libraries
.append("CompilerStub")
2512 while len(LibraryConsumerList
) > 0:
2513 M
= LibraryConsumerList
.pop()
2514 for LibraryName
in M
.Libraries
:
2515 Library
= self
.Platform
.LibraryClasses
[LibraryName
, ':dummy:']
2517 for Key
in self
.Platform
.LibraryClasses
.data
.keys():
2518 if LibraryName
.upper() == Key
.upper():
2519 Library
= self
.Platform
.LibraryClasses
[Key
, ':dummy:']
2522 EdkLogger
.warn("build", "Library [%s] is not found" % LibraryName
, File
=str(M
),
2523 ExtraData
="\t%s [%s]" % (str(Module
), self
.Arch
))
2526 if Library
not in LibraryList
:
2527 LibraryList
.append(Library
)
2528 LibraryConsumerList
.append(Library
)
2529 EdkLogger
.verbose("\t" + LibraryName
+ " : " + str(Library
) + ' ' + str(type(Library
)))
2532 ## Calculate the priority value of the build option
2534 # @param Key Build option definition contain: TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
2536 # @retval Value Priority value based on the priority list.
2538 def CalculatePriorityValue(self
, Key
):
2539 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
.split('_')
2540 PriorityValue
= 0x11111
2542 PriorityValue
&= 0x01111
2543 if ToolChain
== "*":
2544 PriorityValue
&= 0x10111
2546 PriorityValue
&= 0x11011
2547 if CommandType
== "*":
2548 PriorityValue
&= 0x11101
2550 PriorityValue
&= 0x11110
2552 return self
.PrioList
["0x%0.5x" % PriorityValue
]
2555 ## Expand * in build option key
2557 # @param Options Options to be expanded
2559 # @retval options Options expanded
2561 def _ExpandBuildOption(self
, Options
, ModuleStyle
=None):
2568 # Construct a list contain the build options which need override.
2572 # Key[0] -- tool family
2573 # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
2575 if (Key
[0] == self
.BuildRuleFamily
and
2576 (ModuleStyle
is None or len(Key
) < 3 or (len(Key
) > 2 and Key
[2] == ModuleStyle
))):
2577 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
[1].split('_')
2578 if Target
== self
.BuildTarget
or Target
== "*":
2579 if ToolChain
== self
.ToolChain
or ToolChain
== "*":
2580 if Arch
== self
.Arch
or Arch
== "*":
2581 if Options
[Key
].startswith("="):
2582 if OverrideList
.get(Key
[1]) is not None:
2583 OverrideList
.pop(Key
[1])
2584 OverrideList
[Key
[1]] = Options
[Key
]
2587 # Use the highest priority value.
2589 if (len(OverrideList
) >= 2):
2590 KeyList
= OverrideList
.keys()
2591 for Index
in range(len(KeyList
)):
2592 NowKey
= KeyList
[Index
]
2593 Target1
, ToolChain1
, Arch1
, CommandType1
, Attr1
= NowKey
.split("_")
2594 for Index1
in range(len(KeyList
) - Index
- 1):
2595 NextKey
= KeyList
[Index1
+ Index
+ 1]
2597 # Compare two Key, if one is included by another, choose the higher priority one
2599 Target2
, ToolChain2
, Arch2
, CommandType2
, Attr2
= NextKey
.split("_")
2600 if Target1
== Target2
or Target1
== "*" or Target2
== "*":
2601 if ToolChain1
== ToolChain2
or ToolChain1
== "*" or ToolChain2
== "*":
2602 if Arch1
== Arch2
or Arch1
== "*" or Arch2
== "*":
2603 if CommandType1
== CommandType2
or CommandType1
== "*" or CommandType2
== "*":
2604 if Attr1
== Attr2
or Attr1
== "*" or Attr2
== "*":
2605 if self
.CalculatePriorityValue(NowKey
) > self
.CalculatePriorityValue(NextKey
):
2606 if Options
.get((self
.BuildRuleFamily
, NextKey
)) is not None:
2607 Options
.pop((self
.BuildRuleFamily
, NextKey
))
2609 if Options
.get((self
.BuildRuleFamily
, NowKey
)) is not None:
2610 Options
.pop((self
.BuildRuleFamily
, NowKey
))
2613 if ModuleStyle
is not None and len (Key
) > 2:
2614 # Check Module style is EDK or EDKII.
2615 # Only append build option for the matched style module.
2616 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
2618 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
2621 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
2622 # if tool chain family doesn't match, skip it
2623 if Tool
in self
.ToolDefinition
and Family
!= "":
2624 FamilyIsNull
= False
2625 if self
.ToolDefinition
[Tool
].get(TAB_TOD_DEFINES_BUILDRULEFAMILY
, "") != "":
2626 if Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_BUILDRULEFAMILY
]:
2628 elif Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
2631 # expand any wildcard
2632 if Target
== "*" or Target
== self
.BuildTarget
:
2633 if Tag
== "*" or Tag
== self
.ToolChain
:
2634 if Arch
== "*" or Arch
== self
.Arch
:
2635 if Tool
not in BuildOptions
:
2636 BuildOptions
[Tool
] = {}
2637 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
] or Options
[Key
].startswith('='):
2638 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2640 # append options for the same tool except PATH
2642 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
2644 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2645 # Build Option Family has been checked, which need't to be checked again for family.
2646 if FamilyMatch
or FamilyIsNull
:
2650 if ModuleStyle
is not None and len (Key
) > 2:
2651 # Check Module style is EDK or EDKII.
2652 # Only append build option for the matched style module.
2653 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
2655 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
2658 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
2659 # if tool chain family doesn't match, skip it
2660 if Tool
not in self
.ToolDefinition
or Family
== "":
2662 # option has been added before
2663 if Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
2666 # expand any wildcard
2667 if Target
== "*" or Target
== self
.BuildTarget
:
2668 if Tag
== "*" or Tag
== self
.ToolChain
:
2669 if Arch
== "*" or Arch
== self
.Arch
:
2670 if Tool
not in BuildOptions
:
2671 BuildOptions
[Tool
] = {}
2672 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
] or Options
[Key
].startswith('='):
2673 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2675 # append options for the same tool except PATH
2677 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
2679 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2682 ## Append build options in platform to a module
2684 # @param Module The module to which the build options will be appened
2686 # @retval options The options appended with build options in platform
2688 def ApplyBuildOption(self
, Module
):
2689 # Get the different options for the different style module
2690 if Module
.AutoGenVersion
< 0x00010005:
2691 PlatformOptions
= self
.EdkBuildOption
2692 ModuleTypeOptions
= self
.Platform
.GetBuildOptionsByModuleType(EDK_NAME
, Module
.ModuleType
)
2694 PlatformOptions
= self
.EdkIIBuildOption
2695 ModuleTypeOptions
= self
.Platform
.GetBuildOptionsByModuleType(EDKII_NAME
, Module
.ModuleType
)
2696 ModuleTypeOptions
= self
._ExpandBuildOption
(ModuleTypeOptions
)
2697 ModuleOptions
= self
._ExpandBuildOption
(Module
.BuildOptions
)
2698 if Module
in self
.Platform
.Modules
:
2699 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
2700 PlatformModuleOptions
= self
._ExpandBuildOption
(PlatformModule
.BuildOptions
)
2702 PlatformModuleOptions
= {}
2704 BuildRuleOrder
= None
2705 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, ModuleTypeOptions
, PlatformModuleOptions
]:
2706 for Tool
in Options
:
2707 for Attr
in Options
[Tool
]:
2708 if Attr
== TAB_TOD_DEFINES_BUILDRULEORDER
:
2709 BuildRuleOrder
= Options
[Tool
][Attr
]
2711 AllTools
= set(ModuleOptions
.keys() + PlatformOptions
.keys() +
2712 PlatformModuleOptions
.keys() + ModuleTypeOptions
.keys() +
2713 self
.ToolDefinition
.keys())
2715 for Tool
in AllTools
:
2716 if Tool
not in BuildOptions
:
2717 BuildOptions
[Tool
] = {}
2719 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, ModuleTypeOptions
, PlatformModuleOptions
]:
2720 if Tool
not in Options
:
2722 for Attr
in Options
[Tool
]:
2723 Value
= Options
[Tool
][Attr
]
2725 # Do not generate it in Makefile
2727 if Attr
== TAB_TOD_DEFINES_BUILDRULEORDER
:
2729 if Attr
not in BuildOptions
[Tool
]:
2730 BuildOptions
[Tool
][Attr
] = ""
2731 # check if override is indicated
2732 if Value
.startswith('='):
2733 ToolPath
= Value
[1:]
2734 ToolPath
= mws
.handleWsMacro(ToolPath
)
2735 BuildOptions
[Tool
][Attr
] = ToolPath
2737 Value
= mws
.handleWsMacro(Value
)
2739 BuildOptions
[Tool
][Attr
] += " " + Value
2741 BuildOptions
[Tool
][Attr
] = Value
2742 if Module
.AutoGenVersion
< 0x00010005 and self
.Workspace
.UniFlag
is not None:
2744 # Override UNI flag only for EDK module.
2746 if 'BUILD' not in BuildOptions
:
2747 BuildOptions
['BUILD'] = {}
2748 BuildOptions
['BUILD']['FLAGS'] = self
.Workspace
.UniFlag
2749 return BuildOptions
, BuildRuleOrder
2751 Platform
= property(_GetPlatform
)
2752 Name
= property(_GetName
)
2753 Guid
= property(_GetGuid
)
2754 Version
= property(_GetVersion
)
2756 OutputDir
= property(_GetOutputDir
)
2757 BuildDir
= property(_GetBuildDir
)
2758 MakeFileDir
= property(_GetMakeFileDir
)
2759 FdfFile
= property(_GetFdfFile
)
2761 PcdTokenNumber
= property(_GetPcdTokenNumbers
) # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
2762 DynamicPcdList
= property(_GetDynamicPcdList
) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
2763 NonDynamicPcdList
= property(_GetNonDynamicPcdList
) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
2764 NonDynamicPcdDict
= property(_GetNonDynamicPcdDict
)
2765 PackageList
= property(_GetPackageList
)
2767 ToolDefinition
= property(_GetToolDefinition
) # toolcode : tool path
2768 ToolDefinitionFile
= property(_GetToolDefFile
) # toolcode : lib path
2769 ToolChainFamily
= property(_GetToolChainFamily
)
2770 BuildRuleFamily
= property(_GetBuildRuleFamily
)
2771 BuildOption
= property(_GetBuildOptions
) # toolcode : option
2772 EdkBuildOption
= property(_GetEdkBuildOptions
) # edktoolcode : option
2773 EdkIIBuildOption
= property(_GetEdkIIBuildOptions
) # edkiitoolcode : option
2775 BuildCommand
= property(_GetBuildCommand
)
2776 BuildRule
= property(_GetBuildRule
)
2777 ModuleAutoGenList
= property(_GetModuleAutoGenList
)
2778 LibraryAutoGenList
= property(_GetLibraryAutoGenList
)
2779 GenFdsCommand
= property(_GenFdsCommand
)
2781 ## ModuleAutoGen class
2783 # This class encapsules the AutoGen behaviors for the build tools. In addition to
2784 # the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according
2785 # to the [depex] section in module's inf file.
2787 class ModuleAutoGen(AutoGen
):
2788 # call super().__init__ then call the worker function with different parameter count
2789 def __init__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
2793 super(ModuleAutoGen
, self
).__init
__(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
2794 self
._InitWorker
(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
)
2797 ## Cache the timestamps of metafiles of every module in a class variable
2801 def __new__(cls
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
2802 obj
= super(ModuleAutoGen
, cls
).__new
__(cls
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
2803 # check if this module is employed by active platform
2804 if not PlatformAutoGen(Workspace
, args
[0], Target
, Toolchain
, Arch
).ValidModule(MetaFile
):
2805 EdkLogger
.verbose("Module [%s] for [%s] is not employed by active platform\n" \
2810 ## Initialize ModuleAutoGen
2812 # @param Workspace EdkIIWorkspaceBuild object
2813 # @param ModuleFile The path of module file
2814 # @param Target Build target (DEBUG, RELEASE)
2815 # @param Toolchain Name of tool chain
2816 # @param Arch The arch the module supports
2817 # @param PlatformFile Platform meta-file
2819 def _InitWorker(self
, Workspace
, ModuleFile
, Target
, Toolchain
, Arch
, PlatformFile
):
2820 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen module [%s] [%s]" % (ModuleFile
, Arch
))
2821 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (ModuleFile
, Arch
, Toolchain
, Target
)
2823 self
.Workspace
= Workspace
2824 self
.WorkspaceDir
= Workspace
.WorkspaceDir
2826 self
.MetaFile
= ModuleFile
2827 self
.PlatformInfo
= PlatformAutoGen(Workspace
, PlatformFile
, Target
, Toolchain
, Arch
)
2829 self
.SourceDir
= self
.MetaFile
.SubDir
2830 self
.SourceDir
= mws
.relpath(self
.SourceDir
, self
.WorkspaceDir
)
2832 self
.SourceOverrideDir
= None
2833 # use overrided path defined in DSC file
2834 if self
.MetaFile
.Key
in GlobalData
.gOverrideDir
:
2835 self
.SourceOverrideDir
= GlobalData
.gOverrideDir
[self
.MetaFile
.Key
]
2837 self
.ToolChain
= Toolchain
2838 self
.BuildTarget
= Target
2840 self
.ToolChainFamily
= self
.PlatformInfo
.ToolChainFamily
2841 self
.BuildRuleFamily
= self
.PlatformInfo
.BuildRuleFamily
2843 self
.IsMakeFileCreated
= False
2844 self
.IsCodeFileCreated
= False
2845 self
.IsAsBuiltInfCreated
= False
2846 self
.DepexGenerated
= False
2848 self
.BuildDatabase
= self
.Workspace
.BuildDatabase
2849 self
.BuildRuleOrder
= None
2855 self
._Version
= None
2856 self
._ModuleType
= None
2857 self
._ComponentType
= None
2858 self
._PcdIsDriver
= None
2859 self
._AutoGenVersion
= None
2860 self
._LibraryFlag
= None
2861 self
._CustomMakefile
= None
2864 self
._BuildDir
= None
2865 self
._OutputDir
= None
2866 self
._FfsOutputDir
= None
2867 self
._DebugDir
= None
2868 self
._MakeFileDir
= None
2870 self
._IncludePathList
= None
2871 self
._IncludePathLength
= 0
2872 self
._AutoGenFileList
= None
2873 self
._UnicodeFileList
= None
2874 self
._VfrFileList
= None
2875 self
._IdfFileList
= None
2876 self
._SourceFileList
= None
2877 self
._ObjectFileList
= None
2878 self
._BinaryFileList
= None
2880 self
._DependentPackageList
= None
2881 self
._DependentLibraryList
= None
2882 self
._LibraryAutoGenList
= None
2883 self
._DerivedPackageList
= None
2884 self
._ModulePcdList
= None
2885 self
._LibraryPcdList
= None
2886 self
._PcdComments
= OrderedDict()
2887 self
._GuidList
= None
2888 self
._GuidsUsedByPcd
= None
2889 self
._GuidComments
= OrderedDict()
2890 self
._ProtocolList
= None
2891 self
._ProtocolComments
= OrderedDict()
2892 self
._PpiList
= None
2893 self
._PpiComments
= OrderedDict()
2894 self
._DepexList
= None
2895 self
._DepexExpressionList
= None
2896 self
._BuildOption
= None
2897 self
._BuildOptionIncPathList
= None
2898 self
._BuildTargets
= None
2899 self
._IntroBuildTargetList
= None
2900 self
._FinalBuildTargetList
= None
2901 self
._FileTypes
= None
2902 self
._BuildRules
= None
2904 self
._TimeStampPath
= None
2906 self
.AutoGenDepSet
= set()
2909 ## The Modules referenced to this Library
2910 # Only Library has this attribute
2911 self
._ReferenceModules
= []
2913 ## Store the FixedAtBuild Pcds
2915 self
._FixedAtBuildPcds
= []
2920 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
2922 # Get FixedAtBuild Pcds of this Module
2923 def _GetFixedAtBuildPcds(self
):
2924 if self
._FixedAtBuildPcds
:
2925 return self
._FixedAtBuildPcds
2926 for Pcd
in self
.ModulePcdList
:
2927 if Pcd
.Type
!= "FixedAtBuild":
2929 if Pcd
not in self
._FixedAtBuildPcds
:
2930 self
._FixedAtBuildPcds
.append(Pcd
)
2932 return self
._FixedAtBuildPcds
2934 def _GetUniqueBaseName(self
):
2935 BaseName
= self
.Name
2936 for Module
in self
.PlatformInfo
.ModuleAutoGenList
:
2937 if Module
.MetaFile
== self
.MetaFile
:
2939 if Module
.Name
== self
.Name
:
2940 if uuid
.UUID(Module
.Guid
) == uuid
.UUID(self
.Guid
):
2941 EdkLogger
.error("build", FILE_DUPLICATED
, 'Modules have same BaseName and FILE_GUID:\n'
2942 ' %s\n %s' % (Module
.MetaFile
, self
.MetaFile
))
2943 BaseName
= '%s_%s' % (self
.Name
, self
.Guid
)
2946 # Macros could be used in build_rule.txt (also Makefile)
2947 def _GetMacros(self
):
2948 if self
._Macro
is None:
2949 self
._Macro
= OrderedDict()
2950 self
._Macro
["WORKSPACE" ] = self
.WorkspaceDir
2951 self
._Macro
["MODULE_NAME" ] = self
.Name
2952 self
._Macro
["MODULE_NAME_GUID" ] = self
._GetUniqueBaseName
()
2953 self
._Macro
["MODULE_GUID" ] = self
.Guid
2954 self
._Macro
["MODULE_VERSION" ] = self
.Version
2955 self
._Macro
["MODULE_TYPE" ] = self
.ModuleType
2956 self
._Macro
["MODULE_FILE" ] = str(self
.MetaFile
)
2957 self
._Macro
["MODULE_FILE_BASE_NAME" ] = self
.MetaFile
.BaseName
2958 self
._Macro
["MODULE_RELATIVE_DIR" ] = self
.SourceDir
2959 self
._Macro
["MODULE_DIR" ] = self
.SourceDir
2961 self
._Macro
["BASE_NAME" ] = self
.Name
2963 self
._Macro
["ARCH" ] = self
.Arch
2964 self
._Macro
["TOOLCHAIN" ] = self
.ToolChain
2965 self
._Macro
["TOOLCHAIN_TAG" ] = self
.ToolChain
2966 self
._Macro
["TOOL_CHAIN_TAG" ] = self
.ToolChain
2967 self
._Macro
["TARGET" ] = self
.BuildTarget
2969 self
._Macro
["BUILD_DIR" ] = self
.PlatformInfo
.BuildDir
2970 self
._Macro
["BIN_DIR" ] = os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)
2971 self
._Macro
["LIB_DIR" ] = os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)
2972 self
._Macro
["MODULE_BUILD_DIR" ] = self
.BuildDir
2973 self
._Macro
["OUTPUT_DIR" ] = self
.OutputDir
2974 self
._Macro
["DEBUG_DIR" ] = self
.DebugDir
2975 self
._Macro
["DEST_DIR_OUTPUT" ] = self
.OutputDir
2976 self
._Macro
["DEST_DIR_DEBUG" ] = self
.DebugDir
2977 self
._Macro
["PLATFORM_NAME" ] = self
.PlatformInfo
.Name
2978 self
._Macro
["PLATFORM_GUID" ] = self
.PlatformInfo
.Guid
2979 self
._Macro
["PLATFORM_VERSION" ] = self
.PlatformInfo
.Version
2980 self
._Macro
["PLATFORM_RELATIVE_DIR" ] = self
.PlatformInfo
.SourceDir
2981 self
._Macro
["PLATFORM_DIR" ] = mws
.join(self
.WorkspaceDir
, self
.PlatformInfo
.SourceDir
)
2982 self
._Macro
["PLATFORM_OUTPUT_DIR" ] = self
.PlatformInfo
.OutputDir
2983 self
._Macro
["FFS_OUTPUT_DIR" ] = self
.FfsOutputDir
2986 ## Return the module build data object
2987 def _GetModule(self
):
2988 if self
._Module
is None:
2989 self
._Module
= self
.Workspace
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
2992 ## Return the module name
2993 def _GetBaseName(self
):
2994 return self
.Module
.BaseName
2996 ## Return the module DxsFile if exist
2997 def _GetDxsFile(self
):
2998 return self
.Module
.DxsFile
3000 ## Return the module SourceOverridePath
3001 def _GetSourceOverridePath(self
):
3002 return self
.Module
.SourceOverridePath
3004 ## Return the module meta-file GUID
3007 # To build same module more than once, the module path with FILE_GUID overridden has
3008 # the file name FILE_GUIDmodule.inf, but the relative path (self.MetaFile.File) is the realy path
3009 # in DSC. The overridden GUID can be retrieved from file name
3011 if os
.path
.basename(self
.MetaFile
.File
) != os
.path
.basename(self
.MetaFile
.Path
):
3013 # Length of GUID is 36
3015 return os
.path
.basename(self
.MetaFile
.Path
)[:36]
3016 return self
.Module
.Guid
3018 ## Return the module version
3019 def _GetVersion(self
):
3020 return self
.Module
.Version
3022 ## Return the module type
3023 def _GetModuleType(self
):
3024 return self
.Module
.ModuleType
3026 ## Return the component type (for Edk.x style of module)
3027 def _GetComponentType(self
):
3028 return self
.Module
.ComponentType
3030 ## Return the build type
3031 def _GetBuildType(self
):
3032 return self
.Module
.BuildType
3034 ## Return the PCD_IS_DRIVER setting
3035 def _GetPcdIsDriver(self
):
3036 return self
.Module
.PcdIsDriver
3038 ## Return the autogen version, i.e. module meta-file version
3039 def _GetAutoGenVersion(self
):
3040 return self
.Module
.AutoGenVersion
3042 ## Check if the module is library or not
3043 def _IsLibrary(self
):
3044 if self
._LibraryFlag
is None:
3045 if self
.Module
.LibraryClass
is not None and self
.Module
.LibraryClass
!= []:
3046 self
._LibraryFlag
= True
3048 self
._LibraryFlag
= False
3049 return self
._LibraryFlag
3051 ## Check if the module is binary module or not
3052 def _IsBinaryModule(self
):
3053 return self
.Module
.IsBinaryModule
3055 ## Return the directory to store intermediate files of the module
3056 def _GetBuildDir(self
):
3057 if self
._BuildDir
is None:
3058 self
._BuildDir
= path
.join(
3059 self
.PlatformInfo
.BuildDir
,
3062 self
.MetaFile
.BaseName
3064 CreateDirectory(self
._BuildDir
)
3065 return self
._BuildDir
3067 ## Return the directory to store the intermediate object files of the mdoule
3068 def _GetOutputDir(self
):
3069 if self
._OutputDir
is None:
3070 self
._OutputDir
= path
.join(self
.BuildDir
, "OUTPUT")
3071 CreateDirectory(self
._OutputDir
)
3072 return self
._OutputDir
3074 ## Return the directory to store ffs file
3075 def _GetFfsOutputDir(self
):
3076 if self
._FfsOutputDir
is None:
3077 if GlobalData
.gFdfParser
is not None:
3078 self
._FfsOutputDir
= path
.join(self
.PlatformInfo
.BuildDir
, "FV", "Ffs", self
.Guid
+ self
.Name
)
3080 self
._FfsOutputDir
= ''
3081 return self
._FfsOutputDir
3083 ## Return the directory to store auto-gened source files of the mdoule
3084 def _GetDebugDir(self
):
3085 if self
._DebugDir
is None:
3086 self
._DebugDir
= path
.join(self
.BuildDir
, "DEBUG")
3087 CreateDirectory(self
._DebugDir
)
3088 return self
._DebugDir
3090 ## Return the path of custom file
3091 def _GetCustomMakefile(self
):
3092 if self
._CustomMakefile
is None:
3093 self
._CustomMakefile
= {}
3094 for Type
in self
.Module
.CustomMakefile
:
3095 if Type
in gMakeTypeMap
:
3096 MakeType
= gMakeTypeMap
[Type
]
3099 if self
.SourceOverrideDir
is not None:
3100 File
= os
.path
.join(self
.SourceOverrideDir
, self
.Module
.CustomMakefile
[Type
])
3101 if not os
.path
.exists(File
):
3102 File
= os
.path
.join(self
.SourceDir
, self
.Module
.CustomMakefile
[Type
])
3104 File
= os
.path
.join(self
.SourceDir
, self
.Module
.CustomMakefile
[Type
])
3105 self
._CustomMakefile
[MakeType
] = File
3106 return self
._CustomMakefile
3108 ## Return the directory of the makefile
3110 # @retval string The directory string of module's makefile
3112 def _GetMakeFileDir(self
):
3113 return self
.BuildDir
3115 ## Return build command string
3117 # @retval string Build command string
3119 def _GetBuildCommand(self
):
3120 return self
.PlatformInfo
.BuildCommand
3122 ## Get object list of all packages the module and its dependent libraries belong to
3124 # @retval list The list of package object
3126 def _GetDerivedPackageList(self
):
3128 for M
in [self
.Module
] + self
.DependentLibraryList
:
3129 for Package
in M
.Packages
:
3130 if Package
in PackageList
:
3132 PackageList
.append(Package
)
3135 ## Get the depex string
3137 # @return : a string contain all depex expresion.
3138 def _GetDepexExpresionString(self
):
3141 ## DPX_SOURCE IN Define section.
3142 if self
.Module
.DxsFile
:
3144 for M
in [self
.Module
] + self
.DependentLibraryList
:
3145 Filename
= M
.MetaFile
.Path
3146 InfObj
= InfSectionParser
.InfSectionParser(Filename
)
3147 DepexExpresionList
= InfObj
.GetDepexExpresionList()
3148 for DepexExpresion
in DepexExpresionList
:
3149 for key
in DepexExpresion
.keys():
3150 Arch
, ModuleType
= key
3151 DepexExpr
= [x
for x
in DepexExpresion
[key
] if not str(x
).startswith('#')]
3152 # the type of build module is USER_DEFINED.
3153 # All different DEPEX section tags would be copied into the As Built INF file
3154 # and there would be separate DEPEX section tags
3155 if self
.ModuleType
.upper() == SUP_MODULE_USER_DEFINED
:
3156 if (Arch
.upper() == self
.Arch
.upper()) and (ModuleType
.upper() != TAB_ARCH_COMMON
):
3157 DepexList
.append({(Arch
, ModuleType
): DepexExpr
})
3159 if Arch
.upper() == TAB_ARCH_COMMON
or \
3160 (Arch
.upper() == self
.Arch
.upper() and \
3161 ModuleType
.upper() in [TAB_ARCH_COMMON
, self
.ModuleType
.upper()]):
3162 DepexList
.append({(Arch
, ModuleType
): DepexExpr
})
3164 #the type of build module is USER_DEFINED.
3165 if self
.ModuleType
.upper() == SUP_MODULE_USER_DEFINED
:
3166 for Depex
in DepexList
:
3167 for key
in Depex
.keys():
3168 DepexStr
+= '[Depex.%s.%s]\n' % key
3169 DepexStr
+= '\n'.join(['# '+ val
for val
in Depex
[key
]])
3172 return '[Depex.%s]\n' % self
.Arch
3175 #the type of build module not is USER_DEFINED.
3177 for Depex
in DepexList
:
3182 for D
in Depex
.values():
3183 DepexStr
+= ' '.join([val
for val
in D
])
3184 Index
= DepexStr
.find('END')
3185 if Index
> -1 and Index
== len(DepexStr
) - 3:
3186 DepexStr
= DepexStr
[:-3]
3187 DepexStr
= DepexStr
.strip()
3190 DepexStr
= DepexStr
.lstrip('(').rstrip(')').strip()
3192 return '[Depex.%s]\n' % self
.Arch
3193 return '[Depex.%s]\n# ' % self
.Arch
+ DepexStr
3195 ## Merge dependency expression
3197 # @retval list The token list of the dependency expression after parsed
3199 def _GetDepexTokenList(self
):
3200 if self
._DepexList
is None:
3201 self
._DepexList
= {}
3202 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
3203 return self
._DepexList
3205 self
._DepexList
[self
.ModuleType
] = []
3207 for ModuleType
in self
._DepexList
:
3208 DepexList
= self
._DepexList
[ModuleType
]
3210 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
3212 for M
in [self
.Module
] + self
.DependentLibraryList
:
3214 for D
in M
.Depex
[self
.Arch
, ModuleType
]:
3216 DepexList
.append('AND')
3217 DepexList
.append('(')
3219 if DepexList
[-1] == 'END': # no need of a END at this time
3221 DepexList
.append(')')
3224 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexList
))
3225 if 'BEFORE' in DepexList
or 'AFTER' in DepexList
:
3227 if len(DepexList
) > 0:
3228 EdkLogger
.verbose('')
3229 return self
._DepexList
3231 ## Merge dependency expression
3233 # @retval list The token list of the dependency expression after parsed
3235 def _GetDepexExpressionTokenList(self
):
3236 if self
._DepexExpressionList
is None:
3237 self
._DepexExpressionList
= {}
3238 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
3239 return self
._DepexExpressionList
3241 self
._DepexExpressionList
[self
.ModuleType
] = ''
3243 for ModuleType
in self
._DepexExpressionList
:
3244 DepexExpressionList
= self
._DepexExpressionList
[ModuleType
]
3246 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
3248 for M
in [self
.Module
] + self
.DependentLibraryList
:
3250 for D
in M
.DepexExpression
[self
.Arch
, ModuleType
]:
3251 if DepexExpressionList
!= '':
3252 DepexExpressionList
+= ' AND '
3253 DepexExpressionList
+= '('
3254 DepexExpressionList
+= D
3255 DepexExpressionList
= DepexExpressionList
.rstrip('END').strip()
3256 DepexExpressionList
+= ')'
3259 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexExpressionList
))
3260 if 'BEFORE' in DepexExpressionList
or 'AFTER' in DepexExpressionList
:
3262 if len(DepexExpressionList
) > 0:
3263 EdkLogger
.verbose('')
3264 self
._DepexExpressionList
[ModuleType
] = DepexExpressionList
3265 return self
._DepexExpressionList
3267 # Get the tiano core user extension, it is contain dependent library.
3268 # @retval: a list contain tiano core userextension.
3270 def _GetTianoCoreUserExtensionList(self
):
3271 TianoCoreUserExtentionList
= []
3272 for M
in [self
.Module
] + self
.DependentLibraryList
:
3273 Filename
= M
.MetaFile
.Path
3274 InfObj
= InfSectionParser
.InfSectionParser(Filename
)
3275 TianoCoreUserExtenList
= InfObj
.GetUserExtensionTianoCore()
3276 for TianoCoreUserExtent
in TianoCoreUserExtenList
:
3277 for Section
in TianoCoreUserExtent
.keys():
3278 ItemList
= Section
.split(TAB_SPLIT
)
3280 if len(ItemList
) == 4:
3282 if Arch
.upper() == TAB_ARCH_COMMON
or Arch
.upper() == self
.Arch
.upper():
3284 TianoCoreList
.extend([TAB_SECTION_START
+ Section
+ TAB_SECTION_END
])
3285 TianoCoreList
.extend(TianoCoreUserExtent
[Section
][:])
3286 TianoCoreList
.append('\n')
3287 TianoCoreUserExtentionList
.append(TianoCoreList
)
3289 return TianoCoreUserExtentionList
3291 ## Return the list of specification version required for the module
3293 # @retval list The list of specification defined in module file
3295 def _GetSpecification(self
):
3296 return self
.Module
.Specification
3298 ## Tool option for the module build
3300 # @param PlatformInfo The object of PlatformBuildInfo
3301 # @retval dict The dict containing valid options
3303 def _GetModuleBuildOption(self
):
3304 if self
._BuildOption
is None:
3305 self
._BuildOption
, self
.BuildRuleOrder
= self
.PlatformInfo
.ApplyBuildOption(self
.Module
)
3306 if self
.BuildRuleOrder
:
3307 self
.BuildRuleOrder
= ['.%s' % Ext
for Ext
in self
.BuildRuleOrder
.split()]
3308 return self
._BuildOption
3310 ## Get include path list from tool option for the module build
3312 # @retval list The include path list
3314 def _GetBuildOptionIncPathList(self
):
3315 if self
._BuildOptionIncPathList
is None:
3317 # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
3318 # is the former use /I , the Latter used -I to specify include directories
3320 if self
.PlatformInfo
.ToolChainFamily
in ('MSFT'):
3321 BuildOptIncludeRegEx
= gBuildOptIncludePatternMsft
3322 elif self
.PlatformInfo
.ToolChainFamily
in ('INTEL', 'GCC', 'RVCT'):
3323 BuildOptIncludeRegEx
= gBuildOptIncludePatternOther
3326 # New ToolChainFamily, don't known whether there is option to specify include directories
3328 self
._BuildOptionIncPathList
= []
3329 return self
._BuildOptionIncPathList
3331 BuildOptionIncPathList
= []
3332 for Tool
in ('CC', 'PP', 'VFRPP', 'ASLPP', 'ASLCC', 'APP', 'ASM'):
3335 FlagOption
= self
.BuildOption
[Tool
][Attr
]
3339 if self
.PlatformInfo
.ToolChainFamily
!= 'RVCT':
3340 IncPathList
= [NormPath(Path
, self
.Macros
) for Path
in BuildOptIncludeRegEx
.findall(FlagOption
)]
3343 # RVCT may specify a list of directory seperated by commas
3346 for Path
in BuildOptIncludeRegEx
.findall(FlagOption
):
3347 PathList
= GetSplitList(Path
, TAB_COMMA_SPLIT
)
3348 IncPathList
+= [NormPath(PathEntry
, self
.Macros
) for PathEntry
in PathList
]
3351 # EDK II modules must not reference header files outside of the packages they depend on or
3352 # within the module's directory tree. Report error if violation.
3354 if self
.AutoGenVersion
>= 0x00010005 and len(IncPathList
) > 0:
3355 for Path
in IncPathList
:
3356 if (Path
not in self
.IncludePathList
) and (CommonPath([Path
, self
.MetaFile
.Dir
]) != self
.MetaFile
.Dir
):
3357 ErrMsg
= "The include directory for the EDK II module in this line is invalid %s specified in %s FLAGS '%s'" % (Path
, Tool
, FlagOption
)
3358 EdkLogger
.error("build",
3361 File
=str(self
.MetaFile
))
3364 BuildOptionIncPathList
+= IncPathList
3366 self
._BuildOptionIncPathList
= BuildOptionIncPathList
3368 return self
._BuildOptionIncPathList
3370 ## Return a list of files which can be built from source
3372 # What kind of files can be built is determined by build rules in
3373 # $(CONF_DIRECTORY)/build_rule.txt and toolchain family.
3375 def _GetSourceFileList(self
):
3376 if self
._SourceFileList
is None:
3377 self
._SourceFileList
= []
3378 for F
in self
.Module
.Sources
:
3380 if F
.TagName
not in ("", "*", self
.ToolChain
):
3381 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "The toolchain [%s] for processing file [%s] is found, "
3382 "but [%s] is needed" % (F
.TagName
, str(F
), self
.ToolChain
))
3384 # match tool chain family or build rule family
3385 if F
.ToolChainFamily
not in ("", "*", self
.ToolChainFamily
, self
.BuildRuleFamily
):
3388 "The file [%s] must be built by tools of [%s], " \
3389 "but current toolchain family is [%s], buildrule family is [%s]" \
3390 % (str(F
), F
.ToolChainFamily
, self
.ToolChainFamily
, self
.BuildRuleFamily
))
3393 # add the file path into search path list for file including
3394 if F
.Dir
not in self
.IncludePathList
and self
.AutoGenVersion
>= 0x00010005:
3395 self
.IncludePathList
.insert(0, F
.Dir
)
3396 self
._SourceFileList
.append(F
)
3398 self
._MatchBuildRuleOrder
(self
._SourceFileList
)
3400 for F
in self
._SourceFileList
:
3401 self
._ApplyBuildRule
(F
, TAB_UNKNOWN_FILE
)
3402 return self
._SourceFileList
3404 def _MatchBuildRuleOrder(self
, FileList
):
3406 self
._GetModuleBuildOption
()
3407 for SingleFile
in FileList
:
3408 if self
.BuildRuleOrder
and SingleFile
.Ext
in self
.BuildRuleOrder
and SingleFile
.Ext
in self
.BuildRules
:
3409 key
= SingleFile
.Path
.split(SingleFile
.Ext
)[0]
3410 if key
in Order_Dict
:
3411 Order_Dict
[key
].append(SingleFile
.Ext
)
3413 Order_Dict
[key
] = [SingleFile
.Ext
]
3416 for F
in Order_Dict
:
3417 if len(Order_Dict
[F
]) > 1:
3418 Order_Dict
[F
].sort(key
=lambda i
: self
.BuildRuleOrder
.index(i
))
3419 for Ext
in Order_Dict
[F
][1:]:
3420 RemoveList
.append(F
+ Ext
)
3422 for item
in RemoveList
:
3423 FileList
.remove(item
)
3427 ## Return the list of unicode files
3428 def _GetUnicodeFileList(self
):
3429 if self
._UnicodeFileList
is None:
3430 if TAB_UNICODE_FILE
in self
.FileTypes
:
3431 self
._UnicodeFileList
= self
.FileTypes
[TAB_UNICODE_FILE
]
3433 self
._UnicodeFileList
= []
3434 return self
._UnicodeFileList
3436 ## Return the list of vfr files
3437 def _GetVfrFileList(self
):
3438 if self
._VfrFileList
is None:
3439 if TAB_VFR_FILE
in self
.FileTypes
:
3440 self
._VfrFileList
= self
.FileTypes
[TAB_VFR_FILE
]
3442 self
._VfrFileList
= []
3443 return self
._VfrFileList
3445 ## Return the list of Image Definition files
3446 def _GetIdfFileList(self
):
3447 if self
._IdfFileList
is None:
3448 if TAB_IMAGE_FILE
in self
.FileTypes
:
3449 self
._IdfFileList
= self
.FileTypes
[TAB_IMAGE_FILE
]
3451 self
._IdfFileList
= []
3452 return self
._IdfFileList
3454 ## Return a list of files which can be built from binary
3456 # "Build" binary files are just to copy them to build directory.
3458 # @retval list The list of files which can be built later
3460 def _GetBinaryFiles(self
):
3461 if self
._BinaryFileList
is None:
3462 self
._BinaryFileList
= []
3463 for F
in self
.Module
.Binaries
:
3464 if F
.Target
not in ['COMMON', '*'] and F
.Target
!= self
.BuildTarget
:
3466 self
._BinaryFileList
.append(F
)
3467 self
._ApplyBuildRule
(F
, F
.Type
)
3468 return self
._BinaryFileList
3470 def _GetBuildRules(self
):
3471 if self
._BuildRules
is None:
3473 BuildRuleDatabase
= self
.PlatformInfo
.BuildRule
3474 for Type
in BuildRuleDatabase
.FileTypeList
:
3475 #first try getting build rule by BuildRuleFamily
3476 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.BuildRuleFamily
]
3478 # build type is always module type, but ...
3479 if self
.ModuleType
!= self
.BuildType
:
3480 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.BuildRuleFamily
]
3481 #second try getting build rule by ToolChainFamily
3483 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.ToolChainFamily
]
3485 # build type is always module type, but ...
3486 if self
.ModuleType
!= self
.BuildType
:
3487 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.ToolChainFamily
]
3490 RuleObject
= RuleObject
.Instantiate(self
.Macros
)
3491 BuildRules
[Type
] = RuleObject
3492 for Ext
in RuleObject
.SourceFileExtList
:
3493 BuildRules
[Ext
] = RuleObject
3494 self
._BuildRules
= BuildRules
3495 return self
._BuildRules
3497 def _ApplyBuildRule(self
, File
, FileType
):
3498 if self
._BuildTargets
is None:
3499 self
._IntroBuildTargetList
= set()
3500 self
._FinalBuildTargetList
= set()
3501 self
._BuildTargets
= {}
3502 self
._FileTypes
= {}
3504 SubDirectory
= os
.path
.join(self
.OutputDir
, File
.SubDir
)
3505 if not os
.path
.exists(SubDirectory
):
3506 CreateDirectory(SubDirectory
)
3512 # Make sure to get build rule order value
3514 self
._GetModuleBuildOption
()
3516 while Index
< len(SourceList
):
3517 Source
= SourceList
[Index
]
3521 CreateDirectory(Source
.Dir
)
3523 if File
.IsBinary
and File
== Source
and self
._BinaryFileList
is not None and File
in self
._BinaryFileList
:
3524 # Skip all files that are not binary libraries
3525 if not self
.IsLibrary
:
3527 RuleObject
= self
.BuildRules
[TAB_DEFAULT_BINARY_FILE
]
3528 elif FileType
in self
.BuildRules
:
3529 RuleObject
= self
.BuildRules
[FileType
]
3530 elif Source
.Ext
in self
.BuildRules
:
3531 RuleObject
= self
.BuildRules
[Source
.Ext
]
3533 # stop at no more rules
3535 self
._FinalBuildTargetList
.add(LastTarget
)
3538 FileType
= RuleObject
.SourceFileType
3539 if FileType
not in self
._FileTypes
:
3540 self
._FileTypes
[FileType
] = set()
3541 self
._FileTypes
[FileType
].add(Source
)
3543 # stop at STATIC_LIBRARY for library
3544 if self
.IsLibrary
and FileType
== TAB_STATIC_LIBRARY
:
3546 self
._FinalBuildTargetList
.add(LastTarget
)
3549 Target
= RuleObject
.Apply(Source
, self
.BuildRuleOrder
)
3552 self
._FinalBuildTargetList
.add(LastTarget
)
3554 elif not Target
.Outputs
:
3555 # Only do build for target with outputs
3556 self
._FinalBuildTargetList
.add(Target
)
3558 if FileType
not in self
._BuildTargets
:
3559 self
._BuildTargets
[FileType
] = set()
3560 self
._BuildTargets
[FileType
].add(Target
)
3562 if not Source
.IsBinary
and Source
== File
:
3563 self
._IntroBuildTargetList
.add(Target
)
3565 # to avoid cyclic rule
3566 if FileType
in RuleChain
:
3569 RuleChain
.append(FileType
)
3570 SourceList
.extend(Target
.Outputs
)
3572 FileType
= TAB_UNKNOWN_FILE
3574 def _GetTargets(self
):
3575 if self
._BuildTargets
is None:
3576 self
._IntroBuildTargetList
= set()
3577 self
._FinalBuildTargetList
= set()
3578 self
._BuildTargets
= {}
3579 self
._FileTypes
= {}
3581 #TRICK: call _GetSourceFileList to apply build rule for source files
3582 if self
.SourceFileList
:
3585 #TRICK: call _GetBinaryFileList to apply build rule for binary files
3586 if self
.BinaryFileList
:
3589 return self
._BuildTargets
3591 def _GetIntroTargetList(self
):
3593 return self
._IntroBuildTargetList
3595 def _GetFinalTargetList(self
):
3597 return self
._FinalBuildTargetList
3599 def _GetFileTypes(self
):
3601 return self
._FileTypes
3603 ## Get the list of package object the module depends on
3605 # @retval list The package object list
3607 def _GetDependentPackageList(self
):
3608 return self
.Module
.Packages
3610 ## Return the list of auto-generated code file
3612 # @retval list The list of auto-generated file
3614 def _GetAutoGenFileList(self
):
3615 UniStringAutoGenC
= True
3616 IdfStringAutoGenC
= True
3617 UniStringBinBuffer
= StringIO()
3618 IdfGenBinBuffer
= StringIO()
3619 if self
.BuildType
== 'UEFI_HII':
3620 UniStringAutoGenC
= False
3621 IdfStringAutoGenC
= False
3622 if self
._AutoGenFileList
is None:
3623 self
._AutoGenFileList
= {}
3624 AutoGenC
= TemplateString()
3625 AutoGenH
= TemplateString()
3626 StringH
= TemplateString()
3627 StringIdf
= TemplateString()
3628 GenC
.CreateCode(self
, AutoGenC
, AutoGenH
, StringH
, UniStringAutoGenC
, UniStringBinBuffer
, StringIdf
, IdfStringAutoGenC
, IdfGenBinBuffer
)
3630 # AutoGen.c is generated if there are library classes in inf, or there are object files
3632 if str(AutoGenC
) != "" and (len(self
.Module
.LibraryClasses
) > 0
3633 or TAB_OBJECT_FILE
in self
.FileTypes
):
3634 AutoFile
= PathClass(gAutoGenCodeFileName
, self
.DebugDir
)
3635 self
._AutoGenFileList
[AutoFile
] = str(AutoGenC
)
3636 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3637 if str(AutoGenH
) != "":
3638 AutoFile
= PathClass(gAutoGenHeaderFileName
, self
.DebugDir
)
3639 self
._AutoGenFileList
[AutoFile
] = str(AutoGenH
)
3640 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3641 if str(StringH
) != "":
3642 AutoFile
= PathClass(gAutoGenStringFileName
% {"module_name":self
.Name
}, self
.DebugDir
)
3643 self
._AutoGenFileList
[AutoFile
] = str(StringH
)
3644 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3645 if UniStringBinBuffer
is not None and UniStringBinBuffer
.getvalue() != "":
3646 AutoFile
= PathClass(gAutoGenStringFormFileName
% {"module_name":self
.Name
}, self
.OutputDir
)
3647 self
._AutoGenFileList
[AutoFile
] = UniStringBinBuffer
.getvalue()
3648 AutoFile
.IsBinary
= True
3649 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3650 if UniStringBinBuffer
is not None:
3651 UniStringBinBuffer
.close()
3652 if str(StringIdf
) != "":
3653 AutoFile
= PathClass(gAutoGenImageDefFileName
% {"module_name":self
.Name
}, self
.DebugDir
)
3654 self
._AutoGenFileList
[AutoFile
] = str(StringIdf
)
3655 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3656 if IdfGenBinBuffer
is not None and IdfGenBinBuffer
.getvalue() != "":
3657 AutoFile
= PathClass(gAutoGenIdfFileName
% {"module_name":self
.Name
}, self
.OutputDir
)
3658 self
._AutoGenFileList
[AutoFile
] = IdfGenBinBuffer
.getvalue()
3659 AutoFile
.IsBinary
= True
3660 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3661 if IdfGenBinBuffer
is not None:
3662 IdfGenBinBuffer
.close()
3663 return self
._AutoGenFileList
3665 ## Return the list of library modules explicitly or implicityly used by this module
3666 def _GetLibraryList(self
):
3667 if self
._DependentLibraryList
is None:
3668 # only merge library classes and PCD for non-library module
3670 self
._DependentLibraryList
= []
3672 if self
.AutoGenVersion
< 0x00010005:
3673 self
._DependentLibraryList
= self
.PlatformInfo
.ResolveLibraryReference(self
.Module
)
3675 self
._DependentLibraryList
= self
.PlatformInfo
.ApplyLibraryInstance(self
.Module
)
3676 return self
._DependentLibraryList
3679 def UpdateComments(Recver
, Src
):
3681 if Key
not in Recver
:
3683 Recver
[Key
].extend(Src
[Key
])
3684 ## Get the list of PCDs from current module
3686 # @retval list The list of PCD
3688 def _GetModulePcdList(self
):
3689 if self
._ModulePcdList
is None:
3690 # apply PCD settings from platform
3691 self
._ModulePcdList
= self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, self
.Module
.Pcds
)
3692 self
.UpdateComments(self
._PcdComments
, self
.Module
.PcdComments
)
3693 return self
._ModulePcdList
3695 ## Get the list of PCDs from dependent libraries
3697 # @retval list The list of PCD
3699 def _GetLibraryPcdList(self
):
3700 if self
._LibraryPcdList
is None:
3701 Pcds
= OrderedDict()
3702 if not self
.IsLibrary
:
3703 # get PCDs from dependent libraries
3704 for Library
in self
.DependentLibraryList
:
3705 self
.UpdateComments(self
._PcdComments
, Library
.PcdComments
)
3706 for Key
in Library
.Pcds
:
3707 # skip duplicated PCDs
3708 if Key
in self
.Module
.Pcds
or Key
in Pcds
:
3710 Pcds
[Key
] = copy
.copy(Library
.Pcds
[Key
])
3711 # apply PCD settings from platform
3712 self
._LibraryPcdList
= self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, Pcds
)
3714 self
._LibraryPcdList
= []
3715 return self
._LibraryPcdList
3717 ## Get the GUID value mapping
3719 # @retval dict The mapping between GUID cname and its value
3721 def _GetGuidList(self
):
3722 if self
._GuidList
is None:
3723 self
._GuidList
= OrderedDict()
3724 self
._GuidList
.update(self
.Module
.Guids
)
3725 for Library
in self
.DependentLibraryList
:
3726 self
._GuidList
.update(Library
.Guids
)
3727 self
.UpdateComments(self
._GuidComments
, Library
.GuidComments
)
3728 self
.UpdateComments(self
._GuidComments
, self
.Module
.GuidComments
)
3729 return self
._GuidList
3731 def GetGuidsUsedByPcd(self
):
3732 if self
._GuidsUsedByPcd
is None:
3733 self
._GuidsUsedByPcd
= OrderedDict()
3734 self
._GuidsUsedByPcd
.update(self
.Module
.GetGuidsUsedByPcd())
3735 for Library
in self
.DependentLibraryList
:
3736 self
._GuidsUsedByPcd
.update(Library
.GetGuidsUsedByPcd())
3737 return self
._GuidsUsedByPcd
3738 ## Get the protocol value mapping
3740 # @retval dict The mapping between protocol cname and its value
3742 def _GetProtocolList(self
):
3743 if self
._ProtocolList
is None:
3744 self
._ProtocolList
= OrderedDict()
3745 self
._ProtocolList
.update(self
.Module
.Protocols
)
3746 for Library
in self
.DependentLibraryList
:
3747 self
._ProtocolList
.update(Library
.Protocols
)
3748 self
.UpdateComments(self
._ProtocolComments
, Library
.ProtocolComments
)
3749 self
.UpdateComments(self
._ProtocolComments
, self
.Module
.ProtocolComments
)
3750 return self
._ProtocolList
3752 ## Get the PPI value mapping
3754 # @retval dict The mapping between PPI cname and its value
3756 def _GetPpiList(self
):
3757 if self
._PpiList
is None:
3758 self
._PpiList
= OrderedDict()
3759 self
._PpiList
.update(self
.Module
.Ppis
)
3760 for Library
in self
.DependentLibraryList
:
3761 self
._PpiList
.update(Library
.Ppis
)
3762 self
.UpdateComments(self
._PpiComments
, Library
.PpiComments
)
3763 self
.UpdateComments(self
._PpiComments
, self
.Module
.PpiComments
)
3764 return self
._PpiList
3766 ## Get the list of include search path
3768 # @retval list The list path
3770 def _GetIncludePathList(self
):
3771 if self
._IncludePathList
is None:
3772 self
._IncludePathList
= []
3773 if self
.AutoGenVersion
< 0x00010005:
3774 for Inc
in self
.Module
.Includes
:
3775 if Inc
not in self
._IncludePathList
:
3776 self
._IncludePathList
.append(Inc
)
3778 Inc
= path
.join(Inc
, self
.Arch
.capitalize())
3779 if os
.path
.exists(Inc
) and Inc
not in self
._IncludePathList
:
3780 self
._IncludePathList
.append(Inc
)
3781 # Edk module needs to put DEBUG_DIR at the end of search path and not to use SOURCE_DIR all the time
3782 self
._IncludePathList
.append(self
.DebugDir
)
3784 self
._IncludePathList
.append(self
.MetaFile
.Dir
)
3785 self
._IncludePathList
.append(self
.DebugDir
)
3787 for Package
in self
.Module
.Packages
:
3788 PackageDir
= mws
.join(self
.WorkspaceDir
, Package
.MetaFile
.Dir
)
3789 if PackageDir
not in self
._IncludePathList
:
3790 self
._IncludePathList
.append(PackageDir
)
3791 IncludesList
= Package
.Includes
3792 if Package
._PrivateIncludes
:
3793 if not self
.MetaFile
.Path
.startswith(PackageDir
):
3794 IncludesList
= list(set(Package
.Includes
).difference(set(Package
._PrivateIncludes
)))
3795 for Inc
in IncludesList
:
3796 if Inc
not in self
._IncludePathList
:
3797 self
._IncludePathList
.append(str(Inc
))
3798 return self
._IncludePathList
3800 def _GetIncludePathLength(self
):
3801 self
._IncludePathLength
= 0
3802 if self
._IncludePathList
:
3803 for inc
in self
._IncludePathList
:
3804 self
._IncludePathLength
+= len(' ' + inc
)
3805 return self
._IncludePathLength
3807 ## Get HII EX PCDs which maybe used by VFR
3809 # efivarstore used by VFR may relate with HII EX PCDs
3810 # Get the variable name and GUID from efivarstore and HII EX PCD
3811 # List the HII EX PCDs in As Built INF if both name and GUID match.
3813 # @retval list HII EX PCDs
3815 def _GetPcdsMaybeUsedByVfr(self
):
3816 if not self
.SourceFileList
:
3820 for SrcFile
in self
.SourceFileList
:
3821 if SrcFile
.Ext
.lower() != '.vfr':
3823 Vfri
= os
.path
.join(self
.OutputDir
, SrcFile
.BaseName
+ '.i')
3824 if not os
.path
.exists(Vfri
):
3826 VfriFile
= open(Vfri
, 'r')
3827 Content
= VfriFile
.read()
3829 Pos
= Content
.find('efivarstore')
3832 # Make sure 'efivarstore' is the start of efivarstore statement
3833 # In case of the value of 'name' (name = efivarstore) is equal to 'efivarstore'
3836 while Index
>= 0 and Content
[Index
] in ' \t\r\n':
3838 if Index
>= 0 and Content
[Index
] != ';':
3839 Pos
= Content
.find('efivarstore', Pos
+ len('efivarstore'))
3842 # 'efivarstore' must be followed by name and guid
3844 Name
= gEfiVarStoreNamePattern
.search(Content
, Pos
)
3847 Guid
= gEfiVarStoreGuidPattern
.search(Content
, Pos
)
3850 NameArray
= ConvertStringToByteArray('L"' + Name
.group(1) + '"')
3851 NameGuids
.append((NameArray
, GuidStructureStringToGuidString(Guid
.group(1))))
3852 Pos
= Content
.find('efivarstore', Name
.end())
3856 for Pcd
in self
.PlatformInfo
.Platform
.Pcds
.values():
3857 if Pcd
.Type
!= TAB_PCDS_DYNAMIC_EX_HII
:
3859 for SkuName
in Pcd
.SkuInfoList
:
3860 SkuInfo
= Pcd
.SkuInfoList
[SkuName
]
3861 Name
= ConvertStringToByteArray(SkuInfo
.VariableName
)
3862 Value
= GuidValue(SkuInfo
.VariableGuid
, self
.PlatformInfo
.PackageList
, self
.MetaFile
.Path
)
3865 Guid
= GuidStructureStringToGuidString(Value
)
3866 if (Name
, Guid
) in NameGuids
and Pcd
not in HiiExPcds
:
3867 HiiExPcds
.append(Pcd
)
3872 def _GenOffsetBin(self
):
3874 for SourceFile
in self
.Module
.Sources
:
3875 if SourceFile
.Type
.upper() == ".VFR" :
3877 # search the .map file to find the offset of vfr binary in the PE32+/TE file.
3879 VfrUniBaseName
[SourceFile
.BaseName
] = (SourceFile
.BaseName
+ "Bin")
3880 if SourceFile
.Type
.upper() == ".UNI" :
3882 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
3884 VfrUniBaseName
["UniOffsetName"] = (self
.Name
+ "Strings")
3886 if len(VfrUniBaseName
) == 0:
3888 MapFileName
= os
.path
.join(self
.OutputDir
, self
.Name
+ ".map")
3889 EfiFileName
= os
.path
.join(self
.OutputDir
, self
.Name
+ ".efi")
3890 VfrUniOffsetList
= GetVariableOffset(MapFileName
, EfiFileName
, VfrUniBaseName
.values())
3891 if not VfrUniOffsetList
:
3894 OutputName
= '%sOffset.bin' % self
.Name
3895 UniVfrOffsetFileName
= os
.path
.join( self
.OutputDir
, OutputName
)
3898 fInputfile
= open(UniVfrOffsetFileName
, "wb+", 0)
3900 EdkLogger
.error("build", FILE_OPEN_FAILURE
, "File open failed for %s" % UniVfrOffsetFileName
,None)
3902 # Use a instance of StringIO to cache data
3903 fStringIO
= StringIO('')
3905 for Item
in VfrUniOffsetList
:
3906 if (Item
[0].find("Strings") != -1):
3908 # UNI offset in image.
3910 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }
3912 UniGuid
= [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66]
3913 UniGuid
= [chr(ItemGuid
) for ItemGuid
in UniGuid
]
3914 fStringIO
.write(''.join(UniGuid
))
3915 UniValue
= pack ('Q', int (Item
[1], 16))
3916 fStringIO
.write (UniValue
)
3919 # VFR binary offset in image.
3921 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };
3923 VfrGuid
= [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2]
3924 VfrGuid
= [chr(ItemGuid
) for ItemGuid
in VfrGuid
]
3925 fStringIO
.write(''.join(VfrGuid
))
3927 VfrValue
= pack ('Q', int (Item
[1], 16))
3928 fStringIO
.write (VfrValue
)
3930 # write data into file.
3933 fInputfile
.write (fStringIO
.getvalue())
3935 EdkLogger
.error("build", FILE_WRITE_FAILURE
, "Write data to file %s failed, please check whether the "
3936 "file been locked or using by other applications." %UniVfrOffsetFileName
,None)
3942 ## Create AsBuilt INF file the module
3944 def CreateAsBuiltInf(self
, IsOnlyCopy
= False):
3945 self
.OutputFile
= []
3947 if GlobalData
.gBinCacheDest
:
3948 self
.CopyModuleToCache()
3951 if self
.IsAsBuiltInfCreated
:
3954 # Skip the following code for EDK I inf
3955 if self
.AutoGenVersion
< 0x00010005:
3958 # Skip the following code for libraries
3962 # Skip the following code for modules with no source files
3963 if self
.SourceFileList
is None or self
.SourceFileList
== []:
3966 # Skip the following code for modules without any binary files
3967 if self
.BinaryFileList
<> None and self
.BinaryFileList
<> []:
3970 ### TODO: How to handles mixed source and binary modules
3972 # Find all DynamicEx and PatchableInModule PCDs used by this module and dependent libraries
3973 # Also find all packages that the DynamicEx PCDs depend on
3978 PcdTokenSpaceList
= []
3979 for Pcd
in self
.ModulePcdList
+ self
.LibraryPcdList
:
3980 if Pcd
.Type
== TAB_PCDS_PATCHABLE_IN_MODULE
:
3981 PatchablePcds
+= [Pcd
]
3982 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, 'PatchableInModule'))
3983 elif Pcd
.Type
in GenC
.gDynamicExPcd
:
3986 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, 'DynamicEx'))
3987 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, 'Dynamic'))
3988 PcdTokenSpaceList
.append(Pcd
.TokenSpaceGuidCName
)
3989 GuidList
= OrderedDict()
3990 GuidList
.update(self
.GuidList
)
3991 for TokenSpace
in self
.GetGuidsUsedByPcd():
3992 # If token space is not referred by patch PCD or Ex PCD, remove the GUID from GUID list
3993 # The GUIDs in GUIDs section should really be the GUIDs in source INF or referred by Ex an patch PCDs
3994 if TokenSpace
not in PcdTokenSpaceList
and TokenSpace
in GuidList
:
3995 GuidList
.pop(TokenSpace
)
3996 CheckList
= (GuidList
, self
.PpiList
, self
.ProtocolList
, PcdCheckList
)
3997 for Package
in self
.DerivedPackageList
:
3998 if Package
in Packages
:
4000 BeChecked
= (Package
.Guids
, Package
.Ppis
, Package
.Protocols
, Package
.Pcds
)
4002 for Index
in range(len(BeChecked
)):
4003 for Item
in CheckList
[Index
]:
4004 if Item
in BeChecked
[Index
]:
4005 Packages
+= [Package
]
4010 VfrPcds
= self
._GetPcdsMaybeUsedByVfr
()
4011 for Pkg
in self
.PlatformInfo
.PackageList
:
4014 for VfrPcd
in VfrPcds
:
4015 if ((VfrPcd
.TokenCName
, VfrPcd
.TokenSpaceGuidCName
, 'DynamicEx') in Pkg
.Pcds
or
4016 (VfrPcd
.TokenCName
, VfrPcd
.TokenSpaceGuidCName
, 'Dynamic') in Pkg
.Pcds
):
4020 ModuleType
= self
.ModuleType
4021 if ModuleType
== 'UEFI_DRIVER' and self
.DepexGenerated
:
4022 ModuleType
= 'DXE_DRIVER'
4025 if self
.PcdIsDriver
!= '':
4026 DriverType
= self
.PcdIsDriver
4029 MDefs
= self
.Module
.Defines
4032 'module_name' : self
.Name
,
4033 'module_guid' : Guid
,
4034 'module_module_type' : ModuleType
,
4035 'module_version_string' : [MDefs
['VERSION_STRING']] if 'VERSION_STRING' in MDefs
else [],
4036 'pcd_is_driver_string' : [],
4037 'module_uefi_specification_version' : [],
4038 'module_pi_specification_version' : [],
4039 'module_entry_point' : self
.Module
.ModuleEntryPointList
,
4040 'module_unload_image' : self
.Module
.ModuleUnloadImageList
,
4041 'module_constructor' : self
.Module
.ConstructorList
,
4042 'module_destructor' : self
.Module
.DestructorList
,
4043 'module_shadow' : [MDefs
['SHADOW']] if 'SHADOW' in MDefs
else [],
4044 'module_pci_vendor_id' : [MDefs
['PCI_VENDOR_ID']] if 'PCI_VENDOR_ID' in MDefs
else [],
4045 'module_pci_device_id' : [MDefs
['PCI_DEVICE_ID']] if 'PCI_DEVICE_ID' in MDefs
else [],
4046 'module_pci_class_code' : [MDefs
['PCI_CLASS_CODE']] if 'PCI_CLASS_CODE' in MDefs
else [],
4047 'module_pci_revision' : [MDefs
['PCI_REVISION']] if 'PCI_REVISION' in MDefs
else [],
4048 'module_build_number' : [MDefs
['BUILD_NUMBER']] if 'BUILD_NUMBER' in MDefs
else [],
4049 'module_spec' : [MDefs
['SPEC']] if 'SPEC' in MDefs
else [],
4050 'module_uefi_hii_resource_section' : [MDefs
['UEFI_HII_RESOURCE_SECTION']] if 'UEFI_HII_RESOURCE_SECTION' in MDefs
else [],
4051 'module_uni_file' : [MDefs
['MODULE_UNI_FILE']] if 'MODULE_UNI_FILE' in MDefs
else [],
4052 'module_arch' : self
.Arch
,
4053 'package_item' : ['%s' % (Package
.MetaFile
.File
.replace('\\', '/')) for Package
in Packages
],
4055 'patchablepcd_item' : [],
4057 'protocol_item' : [],
4061 'libraryclasses_item' : []
4064 if 'MODULE_UNI_FILE' in MDefs
:
4065 UNIFile
= os
.path
.join(self
.MetaFile
.Dir
, MDefs
['MODULE_UNI_FILE'])
4066 if os
.path
.isfile(UNIFile
):
4067 shutil
.copy2(UNIFile
, self
.OutputDir
)
4069 if self
.AutoGenVersion
> int(gInfSpecVersion
, 0):
4070 AsBuiltInfDict
['module_inf_version'] = '0x%08x' % self
.AutoGenVersion
4072 AsBuiltInfDict
['module_inf_version'] = gInfSpecVersion
4075 AsBuiltInfDict
['pcd_is_driver_string'] += [DriverType
]
4077 if 'UEFI_SPECIFICATION_VERSION' in self
.Specification
:
4078 AsBuiltInfDict
['module_uefi_specification_version'] += [self
.Specification
['UEFI_SPECIFICATION_VERSION']]
4079 if 'PI_SPECIFICATION_VERSION' in self
.Specification
:
4080 AsBuiltInfDict
['module_pi_specification_version'] += [self
.Specification
['PI_SPECIFICATION_VERSION']]
4082 OutputDir
= self
.OutputDir
.replace('\\', '/').strip('/')
4083 DebugDir
= self
.DebugDir
.replace('\\', '/').strip('/')
4084 for Item
in self
.CodaTargetList
:
4085 File
= Item
.Target
.Path
.replace('\\', '/').strip('/').replace(DebugDir
, '').replace(OutputDir
, '').strip('/')
4086 if File
not in self
.OutputFile
:
4087 self
.OutputFile
.append(File
)
4088 if os
.path
.isabs(File
):
4089 File
= File
.replace('\\', '/').strip('/').replace(OutputDir
, '').strip('/')
4090 if Item
.Target
.Ext
.lower() == '.aml':
4091 AsBuiltInfDict
['binary_item'] += ['ASL|' + File
]
4092 elif Item
.Target
.Ext
.lower() == '.acpi':
4093 AsBuiltInfDict
['binary_item'] += ['ACPI|' + File
]
4094 elif Item
.Target
.Ext
.lower() == '.efi':
4095 AsBuiltInfDict
['binary_item'] += ['PE32|' + self
.Name
+ '.efi']
4097 AsBuiltInfDict
['binary_item'] += ['BIN|' + File
]
4098 if self
.DepexGenerated
:
4099 if self
.Name
+ '.depex' not in self
.OutputFile
:
4100 self
.OutputFile
.append(self
.Name
+ '.depex')
4101 if self
.ModuleType
in ['PEIM']:
4102 AsBuiltInfDict
['binary_item'] += ['PEI_DEPEX|' + self
.Name
+ '.depex']
4103 if self
.ModuleType
in ['DXE_DRIVER', 'DXE_RUNTIME_DRIVER', 'DXE_SAL_DRIVER', 'UEFI_DRIVER']:
4104 AsBuiltInfDict
['binary_item'] += ['DXE_DEPEX|' + self
.Name
+ '.depex']
4105 if self
.ModuleType
in ['DXE_SMM_DRIVER']:
4106 AsBuiltInfDict
['binary_item'] += ['SMM_DEPEX|' + self
.Name
+ '.depex']
4108 Bin
= self
._GenOffsetBin
()
4110 AsBuiltInfDict
['binary_item'] += ['BIN|%s' % Bin
]
4111 if Bin
not in self
.OutputFile
:
4112 self
.OutputFile
.append(Bin
)
4114 for Root
, Dirs
, Files
in os
.walk(OutputDir
):
4116 if File
.lower().endswith('.pdb'):
4117 AsBuiltInfDict
['binary_item'] += ['DISPOSABLE|' + File
]
4118 if File
not in self
.OutputFile
:
4119 self
.OutputFile
.append(File
)
4120 HeaderComments
= self
.Module
.HeaderComments
4122 for Index
in range(len(HeaderComments
)):
4123 if HeaderComments
[Index
].find('@BinaryHeader') != -1:
4124 HeaderComments
[Index
] = HeaderComments
[Index
].replace('@BinaryHeader', '@file')
4127 AsBuiltInfDict
['header_comments'] = '\n'.join(HeaderComments
[StartPos
:]).replace(':#', '://')
4128 AsBuiltInfDict
['tail_comments'] = '\n'.join(self
.Module
.TailComments
)
4131 (self
.ProtocolList
, self
._ProtocolComments
, 'protocol_item'),
4132 (self
.PpiList
, self
._PpiComments
, 'ppi_item'),
4133 (GuidList
, self
._GuidComments
, 'guid_item')
4135 for Item
in GenList
:
4136 for CName
in Item
[0]:
4138 if CName
in Item
[1]:
4139 Comments
= '\n '.join(Item
[1][CName
])
4142 Entry
= Comments
+ '\n ' + CName
4143 AsBuiltInfDict
[Item
[2]].append(Entry
)
4144 PatchList
= parsePcdInfoFromMapFile(
4145 os
.path
.join(self
.OutputDir
, self
.Name
+ '.map'),
4146 os
.path
.join(self
.OutputDir
, self
.Name
+ '.efi')
4149 for Pcd
in PatchablePcds
:
4150 TokenCName
= Pcd
.TokenCName
4151 for PcdItem
in GlobalData
.MixedPcd
:
4152 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
4153 TokenCName
= PcdItem
[0]
4155 for PatchPcd
in PatchList
:
4156 if TokenCName
== PatchPcd
[0]:
4161 if Pcd
.DatumType
== 'BOOLEAN':
4162 BoolValue
= Pcd
.DefaultValue
.upper()
4163 if BoolValue
== 'TRUE':
4164 Pcd
.DefaultValue
= '1'
4165 elif BoolValue
== 'FALSE':
4166 Pcd
.DefaultValue
= '0'
4168 if Pcd
.DatumType
in ['UINT8', 'UINT16', 'UINT32', 'UINT64', 'BOOLEAN']:
4169 HexFormat
= '0x%02x'
4170 if Pcd
.DatumType
== 'UINT16':
4171 HexFormat
= '0x%04x'
4172 elif Pcd
.DatumType
== 'UINT32':
4173 HexFormat
= '0x%08x'
4174 elif Pcd
.DatumType
== 'UINT64':
4175 HexFormat
= '0x%016x'
4176 PcdValue
= HexFormat
% int(Pcd
.DefaultValue
, 0)
4178 if Pcd
.MaxDatumSize
is None or Pcd
.MaxDatumSize
== '':
4179 EdkLogger
.error("build", AUTOGEN_ERROR
,
4180 "Unknown [MaxDatumSize] of PCD [%s.%s]" % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
4182 ArraySize
= int(Pcd
.MaxDatumSize
, 0)
4183 PcdValue
= Pcd
.DefaultValue
4184 if PcdValue
[0] != '{':
4186 if PcdValue
[0] == 'L':
4188 PcdValue
= PcdValue
.lstrip('L')
4189 PcdValue
= eval(PcdValue
)
4191 for Index
in range(0, len(PcdValue
)):
4193 CharVal
= ord(PcdValue
[Index
])
4194 NewValue
= NewValue
+ '0x%02x' % (CharVal
& 0x00FF) + ', ' \
4195 + '0x%02x' % (CharVal
>> 8) + ', '
4197 NewValue
= NewValue
+ '0x%02x' % (ord(PcdValue
[Index
]) % 0x100) + ', '
4200 Padding
= Padding
* 2
4201 ArraySize
= ArraySize
/ 2
4202 if ArraySize
< (len(PcdValue
) + 1):
4203 EdkLogger
.error("build", AUTOGEN_ERROR
,
4204 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
4206 if ArraySize
> len(PcdValue
) + 1:
4207 NewValue
= NewValue
+ Padding
* (ArraySize
- len(PcdValue
) - 1)
4208 PcdValue
= NewValue
+ Padding
.strip().rstrip(',') + '}'
4209 elif len(PcdValue
.split(',')) <= ArraySize
:
4210 PcdValue
= PcdValue
.rstrip('}') + ', 0x00' * (ArraySize
- len(PcdValue
.split(',')))
4213 EdkLogger
.error("build", AUTOGEN_ERROR
,
4214 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
4216 PcdItem
= '%s.%s|%s|0x%X' % \
4217 (Pcd
.TokenSpaceGuidCName
, TokenCName
, PcdValue
, PatchPcd
[1])
4219 if (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in self
._PcdComments
:
4220 PcdComments
= '\n '.join(self
._PcdComments
[Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
])
4222 PcdItem
= PcdComments
+ '\n ' + PcdItem
4223 AsBuiltInfDict
['patchablepcd_item'].append(PcdItem
)
4226 for Pcd
in Pcds
+ VfrPcds
:
4231 TokenCName
= Pcd
.TokenCName
4232 for PcdItem
in GlobalData
.MixedPcd
:
4233 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
4234 TokenCName
= PcdItem
[0]
4236 if Pcd
.Type
== TAB_PCDS_DYNAMIC_EX_HII
:
4237 for SkuName
in Pcd
.SkuInfoList
:
4238 SkuInfo
= Pcd
.SkuInfoList
[SkuName
]
4239 SkuId
= SkuInfo
.SkuId
4240 HiiInfo
= '## %s|%s|%s' % (SkuInfo
.VariableName
, SkuInfo
.VariableGuid
, SkuInfo
.VariableOffset
)
4244 # Don't generate duplicated HII PCD
4246 if (SkuId
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in HiiPcds
:
4249 HiiPcds
.append((SkuId
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
4250 if (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in self
._PcdComments
:
4251 PcdCommentList
= self
._PcdComments
[Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
][:]
4255 for Index
, Comment
in enumerate(PcdCommentList
):
4256 for Usage
in UsageList
:
4257 if Comment
.find(Usage
) != -1:
4261 if UsageIndex
!= -1:
4262 PcdCommentList
[UsageIndex
] = '## %s %s %s' % (UsageStr
, HiiInfo
, PcdCommentList
[UsageIndex
].replace(UsageStr
, ''))
4264 PcdCommentList
.append('## UNDEFINED ' + HiiInfo
)
4265 PcdComments
= '\n '.join(PcdCommentList
)
4266 PcdEntry
= Pcd
.TokenSpaceGuidCName
+ '.' + TokenCName
4268 PcdEntry
= PcdComments
+ '\n ' + PcdEntry
4269 AsBuiltInfDict
['pcd_item'] += [PcdEntry
]
4270 for Item
in self
.BuildOption
:
4271 if 'FLAGS' in self
.BuildOption
[Item
]:
4272 AsBuiltInfDict
['flags_item'] += ['%s:%s_%s_%s_%s_FLAGS = %s' % (self
.ToolChainFamily
, self
.BuildTarget
, self
.ToolChain
, self
.Arch
, Item
, self
.BuildOption
[Item
]['FLAGS'].strip())]
4274 # Generated LibraryClasses section in comments.
4275 for Library
in self
.LibraryAutoGenList
:
4276 AsBuiltInfDict
['libraryclasses_item'] += [Library
.MetaFile
.File
.replace('\\', '/')]
4278 # Generated UserExtensions TianoCore section.
4279 # All tianocore user extensions are copied.
4281 for TianoCore
in self
._GetTianoCoreUserExtensionList
():
4282 UserExtStr
+= '\n'.join(TianoCore
)
4283 ExtensionFile
= os
.path
.join(self
.MetaFile
.Dir
, TianoCore
[1])
4284 if os
.path
.isfile(ExtensionFile
):
4285 shutil
.copy2(ExtensionFile
, self
.OutputDir
)
4286 AsBuiltInfDict
['userextension_tianocore_item'] = UserExtStr
4288 # Generated depex expression section in comments.
4289 AsBuiltInfDict
['depexsection_item'] = ''
4290 DepexExpresion
= self
._GetDepexExpresionString
()
4292 AsBuiltInfDict
['depexsection_item'] = DepexExpresion
4294 AsBuiltInf
= TemplateString()
4295 AsBuiltInf
.Append(gAsBuiltInfHeaderString
.Replace(AsBuiltInfDict
))
4297 SaveFileOnChange(os
.path
.join(self
.OutputDir
, self
.Name
+ '.inf'), str(AsBuiltInf
), False)
4299 self
.IsAsBuiltInfCreated
= True
4300 if GlobalData
.gBinCacheDest
:
4301 self
.CopyModuleToCache()
4303 def CopyModuleToCache(self
):
4304 FileDir
= path
.join(GlobalData
.gBinCacheDest
, self
.Arch
, self
.SourceDir
, self
.MetaFile
.BaseName
)
4305 CreateDirectory (FileDir
)
4306 HashFile
= path
.join(self
.BuildDir
, self
.Name
+ '.hash')
4307 ModuleFile
= path
.join(self
.OutputDir
, self
.Name
+ '.inf')
4308 if os
.path
.exists(HashFile
):
4309 shutil
.copy2(HashFile
, FileDir
)
4310 if os
.path
.exists(ModuleFile
):
4311 shutil
.copy2(ModuleFile
, FileDir
)
4312 if not self
.OutputFile
:
4313 Ma
= self
.Workspace
.BuildDatabase
[PathClass(ModuleFile
), self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
4314 self
.OutputFile
= Ma
.Binaries
4316 for File
in self
.OutputFile
:
4318 if not os
.path
.isabs(File
):
4319 File
= os
.path
.join(self
.OutputDir
, File
)
4320 if os
.path
.exists(File
):
4321 shutil
.copy2(File
, FileDir
)
4323 def AttemptModuleCacheCopy(self
):
4324 if self
.IsBinaryModule
:
4326 FileDir
= path
.join(GlobalData
.gBinCacheSource
, self
.Arch
, self
.SourceDir
, self
.MetaFile
.BaseName
)
4327 HashFile
= path
.join(FileDir
, self
.Name
+ '.hash')
4328 if os
.path
.exists(HashFile
):
4329 f
= open(HashFile
, 'r')
4330 CacheHash
= f
.read()
4332 if GlobalData
.gModuleHash
[self
.Arch
][self
.Name
]:
4333 if CacheHash
== GlobalData
.gModuleHash
[self
.Arch
][self
.Name
]:
4334 for root
, dir, files
in os
.walk(FileDir
):
4336 if self
.Name
+ '.hash' in f
:
4337 shutil
.copy2(HashFile
, self
.BuildDir
)
4339 File
= path
.join(root
, f
)
4340 shutil
.copy2(File
, self
.OutputDir
)
4341 if self
.Name
== "PcdPeim" or self
.Name
== "PcdDxe":
4342 CreatePcdDatabaseCode(self
, TemplateString(), TemplateString())
4346 ## Create makefile for the module and its dependent libraries
4348 # @param CreateLibraryMakeFile Flag indicating if or not the makefiles of
4349 # dependent libraries will be created
4351 def CreateMakeFile(self
, CreateLibraryMakeFile
=True, GenFfsList
= []):
4352 # Ignore generating makefile when it is a binary module
4353 if self
.IsBinaryModule
:
4356 if self
.IsMakeFileCreated
:
4358 self
.GenFfsList
= GenFfsList
4359 if not self
.IsLibrary
and CreateLibraryMakeFile
:
4360 for LibraryAutoGen
in self
.LibraryAutoGenList
:
4361 LibraryAutoGen
.CreateMakeFile()
4366 if len(self
.CustomMakefile
) == 0:
4367 Makefile
= GenMake
.ModuleMakefile(self
)
4369 Makefile
= GenMake
.CustomMakefile(self
)
4370 if Makefile
.Generate():
4371 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated makefile for module %s [%s]" %
4372 (self
.Name
, self
.Arch
))
4374 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of makefile for module %s [%s]" %
4375 (self
.Name
, self
.Arch
))
4377 self
.CreateTimeStamp(Makefile
)
4378 self
.IsMakeFileCreated
= True
4380 def CopyBinaryFiles(self
):
4381 for File
in self
.Module
.Binaries
:
4383 DstPath
= os
.path
.join(self
.OutputDir
, os
.path
.basename(SrcPath
))
4384 CopyLongFilePath(SrcPath
, DstPath
)
4385 ## Create autogen code for the module and its dependent libraries
4387 # @param CreateLibraryCodeFile Flag indicating if or not the code of
4388 # dependent libraries will be created
4390 def CreateCodeFile(self
, CreateLibraryCodeFile
=True):
4391 if self
.IsCodeFileCreated
:
4394 # Need to generate PcdDatabase even PcdDriver is binarymodule
4395 if self
.IsBinaryModule
and self
.PcdIsDriver
!= '':
4396 CreatePcdDatabaseCode(self
, TemplateString(), TemplateString())
4398 if self
.IsBinaryModule
:
4400 self
.CopyBinaryFiles()
4403 if not self
.IsLibrary
and CreateLibraryCodeFile
:
4404 for LibraryAutoGen
in self
.LibraryAutoGenList
:
4405 LibraryAutoGen
.CreateCodeFile()
4411 IgoredAutoGenList
= []
4413 for File
in self
.AutoGenFileList
:
4414 if GenC
.Generate(File
.Path
, self
.AutoGenFileList
[File
], File
.IsBinary
):
4415 #Ignore Edk AutoGen.c
4416 if self
.AutoGenVersion
< 0x00010005 and File
.Name
== 'AutoGen.c':
4419 AutoGenList
.append(str(File
))
4421 IgoredAutoGenList
.append(str(File
))
4423 # Skip the following code for EDK I inf
4424 if self
.AutoGenVersion
< 0x00010005:
4427 for ModuleType
in self
.DepexList
:
4428 # Ignore empty [depex] section or [depex] section for "USER_DEFINED" module
4429 if len(self
.DepexList
[ModuleType
]) == 0 or ModuleType
== "USER_DEFINED":
4432 Dpx
= GenDepex
.DependencyExpression(self
.DepexList
[ModuleType
], ModuleType
, True)
4433 DpxFile
= gAutoGenDepexFileName
% {"module_name" : self
.Name
}
4435 if len(Dpx
.PostfixNotation
) <> 0:
4436 self
.DepexGenerated
= True
4438 if Dpx
.Generate(path
.join(self
.OutputDir
, DpxFile
)):
4439 AutoGenList
.append(str(DpxFile
))
4441 IgoredAutoGenList
.append(str(DpxFile
))
4443 if IgoredAutoGenList
== []:
4444 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] files for module %s [%s]" %
4445 (" ".join(AutoGenList
), self
.Name
, self
.Arch
))
4446 elif AutoGenList
== []:
4447 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of [%s] files for module %s [%s]" %
4448 (" ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
4450 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] (skipped %s) files for module %s [%s]" %
4451 (" ".join(AutoGenList
), " ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
4453 self
.IsCodeFileCreated
= True
4456 ## Summarize the ModuleAutoGen objects of all libraries used by this module
4457 def _GetLibraryAutoGenList(self
):
4458 if self
._LibraryAutoGenList
is None:
4459 self
._LibraryAutoGenList
= []
4460 for Library
in self
.DependentLibraryList
:
4467 self
.PlatformInfo
.MetaFile
4469 if La
not in self
._LibraryAutoGenList
:
4470 self
._LibraryAutoGenList
.append(La
)
4471 for Lib
in La
.CodaTargetList
:
4472 self
._ApplyBuildRule
(Lib
.Target
, TAB_UNKNOWN_FILE
)
4473 return self
._LibraryAutoGenList
4475 def GenModuleHash(self
):
4476 if self
.Arch
not in GlobalData
.gModuleHash
:
4477 GlobalData
.gModuleHash
[self
.Arch
] = {}
4479 # Add Platform level hash
4480 m
.update(GlobalData
.gPlatformHash
)
4481 # Add Package level hash
4482 if self
.DependentPackageList
:
4483 for Pkg
in self
.DependentPackageList
:
4484 if Pkg
.PackageName
in GlobalData
.gPackageHash
[self
.Arch
]:
4485 m
.update(GlobalData
.gPackageHash
[self
.Arch
][Pkg
.PackageName
])
4488 if self
.LibraryAutoGenList
:
4489 for Lib
in self
.LibraryAutoGenList
:
4490 if Lib
.Name
not in GlobalData
.gModuleHash
[self
.Arch
]:
4492 m
.update(GlobalData
.gModuleHash
[self
.Arch
][Lib
.Name
])
4495 f
= open(str(self
.MetaFile
), 'r')
4499 # Add Module's source files
4500 if self
.SourceFileList
:
4501 for File
in self
.SourceFileList
:
4502 f
= open(str(File
), 'r')
4507 ModuleHashFile
= path
.join(self
.BuildDir
, self
.Name
+ ".hash")
4508 if self
.Name
not in GlobalData
.gModuleHash
[self
.Arch
]:
4509 GlobalData
.gModuleHash
[self
.Arch
][self
.Name
] = m
.hexdigest()
4510 if GlobalData
.gBinCacheSource
:
4511 CacheValid
= self
.AttemptModuleCacheCopy()
4514 return SaveFileOnChange(ModuleHashFile
, m
.hexdigest(), True)
4516 ## Decide whether we can skip the ModuleAutoGen process
4517 def CanSkipbyHash(self
):
4518 if GlobalData
.gUseHashCache
:
4519 return not self
.GenModuleHash()
4521 ## Decide whether we can skip the ModuleAutoGen process
4522 # If any source file is newer than the module than we cannot skip
4525 if not os
.path
.exists(self
.GetTimeStampPath()):
4527 #last creation time of the module
4528 DstTimeStamp
= os
.stat(self
.GetTimeStampPath())[8]
4530 SrcTimeStamp
= self
.Workspace
._SrcTimeStamp
4531 if SrcTimeStamp
> DstTimeStamp
:
4534 with
open(self
.GetTimeStampPath(),'r') as f
:
4536 source
= source
.rstrip('\n')
4537 if not os
.path
.exists(source
):
4539 if source
not in ModuleAutoGen
.TimeDict
:
4540 ModuleAutoGen
.TimeDict
[source
] = os
.stat(source
)[8]
4541 if ModuleAutoGen
.TimeDict
[source
] > DstTimeStamp
:
4545 def GetTimeStampPath(self
):
4546 if self
._TimeStampPath
is None:
4547 self
._TimeStampPath
= os
.path
.join(self
.MakeFileDir
, 'AutoGenTimeStamp')
4548 return self
._TimeStampPath
4549 def CreateTimeStamp(self
, Makefile
):
4553 FileSet
.add (self
.MetaFile
.Path
)
4555 for SourceFile
in self
.Module
.Sources
:
4556 FileSet
.add (SourceFile
.Path
)
4558 for Lib
in self
.DependentLibraryList
:
4559 FileSet
.add (Lib
.MetaFile
.Path
)
4561 for f
in self
.AutoGenDepSet
:
4562 FileSet
.add (f
.Path
)
4564 if os
.path
.exists (self
.GetTimeStampPath()):
4565 os
.remove (self
.GetTimeStampPath())
4566 with
open(self
.GetTimeStampPath(), 'w+') as file:
4570 Module
= property(_GetModule
)
4571 Name
= property(_GetBaseName
)
4572 Guid
= property(_GetGuid
)
4573 Version
= property(_GetVersion
)
4574 ModuleType
= property(_GetModuleType
)
4575 ComponentType
= property(_GetComponentType
)
4576 BuildType
= property(_GetBuildType
)
4577 PcdIsDriver
= property(_GetPcdIsDriver
)
4578 AutoGenVersion
= property(_GetAutoGenVersion
)
4579 Macros
= property(_GetMacros
)
4580 Specification
= property(_GetSpecification
)
4582 IsLibrary
= property(_IsLibrary
)
4583 IsBinaryModule
= property(_IsBinaryModule
)
4584 BuildDir
= property(_GetBuildDir
)
4585 OutputDir
= property(_GetOutputDir
)
4586 FfsOutputDir
= property(_GetFfsOutputDir
)
4587 DebugDir
= property(_GetDebugDir
)
4588 MakeFileDir
= property(_GetMakeFileDir
)
4589 CustomMakefile
= property(_GetCustomMakefile
)
4591 IncludePathList
= property(_GetIncludePathList
)
4592 IncludePathLength
= property(_GetIncludePathLength
)
4593 AutoGenFileList
= property(_GetAutoGenFileList
)
4594 UnicodeFileList
= property(_GetUnicodeFileList
)
4595 VfrFileList
= property(_GetVfrFileList
)
4596 SourceFileList
= property(_GetSourceFileList
)
4597 BinaryFileList
= property(_GetBinaryFiles
) # FileType : [File List]
4598 Targets
= property(_GetTargets
)
4599 IntroTargetList
= property(_GetIntroTargetList
)
4600 CodaTargetList
= property(_GetFinalTargetList
)
4601 FileTypes
= property(_GetFileTypes
)
4602 BuildRules
= property(_GetBuildRules
)
4603 IdfFileList
= property(_GetIdfFileList
)
4605 DependentPackageList
= property(_GetDependentPackageList
)
4606 DependentLibraryList
= property(_GetLibraryList
)
4607 LibraryAutoGenList
= property(_GetLibraryAutoGenList
)
4608 DerivedPackageList
= property(_GetDerivedPackageList
)
4610 ModulePcdList
= property(_GetModulePcdList
)
4611 LibraryPcdList
= property(_GetLibraryPcdList
)
4612 GuidList
= property(_GetGuidList
)
4613 ProtocolList
= property(_GetProtocolList
)
4614 PpiList
= property(_GetPpiList
)
4615 DepexList
= property(_GetDepexTokenList
)
4616 DxsFile
= property(_GetDxsFile
)
4617 DepexExpressionList
= property(_GetDepexExpressionTokenList
)
4618 BuildOption
= property(_GetModuleBuildOption
)
4619 BuildOptionIncPathList
= property(_GetBuildOptionIncPathList
)
4620 BuildCommand
= property(_GetBuildCommand
)
4622 FixedAtBuildPcds
= property(_GetFixedAtBuildPcds
)
4624 # This acts like the main() function for the script, unless it is 'import'ed into another script.
4625 if __name__
== '__main__':