2 # Generate AutoGen.h, AutoGen.c and *.depex files
4 # Copyright (c) 2007 - 2015, 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
24 from StringIO
import StringIO
26 from StrGather
import *
27 from BuildEngine
import BuildRule
29 from Common
.LongFilePathSupport
import CopyLongFilePath
30 from Common
.BuildToolError
import *
31 from Common
.DataType
import *
32 from Common
.Misc
import *
33 from Common
.String
import *
34 import Common
.GlobalData
as GlobalData
35 from GenFds
.FdfParser
import *
36 from CommonDataClass
.CommonClass
import SkuInfoClass
37 from Workspace
.BuildClassObject
import *
38 from GenPatchPcdTable
.GenPatchPcdTable
import parsePcdInfoFromMapFile
39 import Common
.VpdInfoFile
as VpdInfoFile
40 from GenPcdDb
import CreatePcdDatabaseCode
41 from Workspace
.MetaFileCommentParser
import UsageList
43 import InfSectionParser
45 ## Regular expression for splitting Dependency Expression string into tokens
46 gDepexTokenPattern
= re
.compile("(\(|\)|\w+| \S+\.inf)")
49 # Match name = variable
51 gEfiVarStoreNamePattern
= re
.compile("\s*name\s*=\s*(\w+)")
53 # The format of guid in efivarstore statement likes following and must be correct:
54 # guid = {0xA04A27f4, 0xDF00, 0x4D42, {0xB5, 0x52, 0x39, 0x51, 0x13, 0x02, 0x11, 0x3D}}
56 gEfiVarStoreGuidPattern
= re
.compile("\s*guid\s*=\s*({.*?{.*?}\s*})")
58 ## Mapping Makefile type
59 gMakeTypeMap
= {"MSFT":"nmake", "GCC":"gmake"}
62 ## Build rule configuration file
63 gDefaultBuildRuleFile
= 'Conf/build_rule.txt'
65 ## Build rule default version
66 AutoGenReqBuildRuleVerNum
= "0.1"
68 ## default file name for AutoGen
69 gAutoGenCodeFileName
= "AutoGen.c"
70 gAutoGenHeaderFileName
= "AutoGen.h"
71 gAutoGenStringFileName
= "%(module_name)sStrDefs.h"
72 gAutoGenStringFormFileName
= "%(module_name)sStrDefs.hpk"
73 gAutoGenDepexFileName
= "%(module_name)s.depex"
75 gInfSpecVersion
= "0x00010017"
78 # Template string to generic AsBuilt INF
80 gAsBuiltInfHeaderString
= TemplateString("""${header_comments}
86 INF_VERSION = ${module_inf_version}
87 BASE_NAME = ${module_name}
88 FILE_GUID = ${module_guid}
89 MODULE_TYPE = ${module_module_type}${BEGIN}
90 VERSION_STRING = ${module_version_string}${END}${BEGIN}
91 PCD_IS_DRIVER = ${pcd_is_driver_string}${END}${BEGIN}
92 UEFI_SPECIFICATION_VERSION = ${module_uefi_specification_version}${END}${BEGIN}
93 PI_SPECIFICATION_VERSION = ${module_pi_specification_version}${END}${BEGIN}
94 ENTRY_POINT = ${module_entry_point}${END}${BEGIN}
95 UNLOAD_IMAGE = ${module_unload_image}${END}${BEGIN}
96 CONSTRUCTOR = ${module_constructor}${END}${BEGIN}
97 DESTRUCTOR = ${module_destructor}${END}${BEGIN}
98 SHADOW = ${module_shadow}${END}${BEGIN}
99 PCI_VENDOR_ID = ${module_pci_vendor_id}${END}${BEGIN}
100 PCI_DEVICE_ID = ${module_pci_device_id}${END}${BEGIN}
101 PCI_CLASS_CODE = ${module_pci_class_code}${END}${BEGIN}
102 PCI_REVISION = ${module_pci_revision}${END}${BEGIN}
103 BUILD_NUMBER = ${module_build_number}${END}${BEGIN}
104 SPEC = ${module_spec}${END}${BEGIN}
105 UEFI_HII_RESOURCE_SECTION = ${module_uefi_hii_resource_section}${END}${BEGIN}
106 MODULE_UNI_FILE = ${module_uni_file}${END}
108 [Packages.${module_arch}]${BEGIN}
109 ${package_item}${END}
111 [Binaries.${module_arch}]${BEGIN}
114 [PatchPcd.${module_arch}]${BEGIN}
118 [Protocols.${module_arch}]${BEGIN}
122 [Ppis.${module_arch}]${BEGIN}
126 [Guids.${module_arch}]${BEGIN}
130 [PcdEx.${module_arch}]${BEGIN}
134 [LibraryClasses.${module_arch}]
135 ## @LIB_INSTANCES${BEGIN}
136 # ${libraryclasses_item}${END}
142 [BuildOptions.${module_arch}]
144 ## ${flags_item}${END}
147 ## Base class for AutoGen
149 # This class just implements the cache mechanism of AutoGen objects.
151 class AutoGen(object):
152 # database to maintain the objects of xxxAutoGen
153 _CACHE_
= {} # (BuildTarget, ToolChain) : {ARCH : {platform file: AutoGen object}}}
157 # @param Class class object of real AutoGen class
158 # (WorkspaceAutoGen, ModuleAutoGen or PlatformAutoGen)
159 # @param Workspace Workspace directory or WorkspaceAutoGen object
160 # @param MetaFile The path of meta file
161 # @param Target Build target
162 # @param Toolchain Tool chain name
163 # @param Arch Target arch
164 # @param *args The specific class related parameters
165 # @param **kwargs The specific class related dict parameters
167 def __new__(Class
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
168 # check if the object has been created
169 Key
= (Target
, Toolchain
)
170 if Key
not in Class
._CACHE
_ or Arch
not in Class
._CACHE
_[Key
] \
171 or MetaFile
not in Class
._CACHE
_[Key
][Arch
]:
172 AutoGenObject
= super(AutoGen
, Class
).__new
__(Class
)
173 # call real constructor
174 if not AutoGenObject
._Init
(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
176 if Key
not in Class
._CACHE
_:
177 Class
._CACHE
_[Key
] = {}
178 if Arch
not in Class
._CACHE
_[Key
]:
179 Class
._CACHE
_[Key
][Arch
] = {}
180 Class
._CACHE
_[Key
][Arch
][MetaFile
] = AutoGenObject
182 AutoGenObject
= Class
._CACHE
_[Key
][Arch
][MetaFile
]
188 # The file path of platform file will be used to represent hash value of this object
190 # @retval int Hash value of the file path of platform file
193 return hash(self
.MetaFile
)
197 # The file path of platform file will be used to represent this object
199 # @retval string String of platform file path
202 return str(self
.MetaFile
)
205 def __eq__(self
, Other
):
206 return Other
and self
.MetaFile
== Other
208 ## Workspace AutoGen class
210 # This class is used mainly to control the whole platform build for different
211 # architecture. This class will generate top level makefile.
213 class WorkspaceAutoGen(AutoGen
):
214 ## Real constructor of WorkspaceAutoGen
216 # This method behaves the same as __init__ except that it needs explicit invoke
217 # (in super class's __new__ method)
219 # @param WorkspaceDir Root directory of workspace
220 # @param ActivePlatform Meta-file of active platform
221 # @param Target Build target
222 # @param Toolchain Tool chain name
223 # @param ArchList List of architecture of current build
224 # @param MetaFileDb Database containing meta-files
225 # @param BuildConfig Configuration of build
226 # @param ToolDefinition Tool chain definitions
227 # @param FlashDefinitionFile File of flash definition
228 # @param Fds FD list to be generated
229 # @param Fvs FV list to be generated
230 # @param Caps Capsule list to be generated
231 # @param SkuId SKU id from command line
233 def _Init(self
, WorkspaceDir
, ActivePlatform
, Target
, Toolchain
, ArchList
, MetaFileDb
,
234 BuildConfig
, ToolDefinition
, FlashDefinitionFile
='', Fds
=None, Fvs
=None, Caps
=None, SkuId
='', UniFlag
=None,
235 Progress
=None, BuildModule
=None):
242 self
.BuildDatabase
= MetaFileDb
243 self
.MetaFile
= ActivePlatform
244 self
.WorkspaceDir
= WorkspaceDir
245 self
.Platform
= self
.BuildDatabase
[self
.MetaFile
, 'COMMON', Target
, Toolchain
]
246 GlobalData
.gActivePlatform
= self
.Platform
247 self
.BuildTarget
= Target
248 self
.ToolChain
= Toolchain
249 self
.ArchList
= ArchList
251 self
.UniFlag
= UniFlag
253 self
.TargetTxt
= BuildConfig
254 self
.ToolDef
= ToolDefinition
255 self
.FdfFile
= FlashDefinitionFile
256 self
.FdTargetList
= Fds
257 self
.FvTargetList
= Fvs
258 self
.CapTargetList
= Caps
259 self
.AutoGenObjectList
= []
261 # there's many relative directory operations, so ...
262 os
.chdir(self
.WorkspaceDir
)
267 if not self
.ArchList
:
268 ArchList
= set(self
.Platform
.SupArchList
)
270 ArchList
= set(self
.ArchList
) & set(self
.Platform
.SupArchList
)
272 EdkLogger
.error("build", PARAMETER_INVALID
,
273 ExtraData
= "Invalid ARCH specified. [Valid ARCH: %s]" % (" ".join(self
.Platform
.SupArchList
)))
274 elif self
.ArchList
and len(ArchList
) != len(self
.ArchList
):
275 SkippedArchList
= set(self
.ArchList
).symmetric_difference(set(self
.Platform
.SupArchList
))
276 EdkLogger
.verbose("\nArch [%s] is ignored because the platform supports [%s] only!"
277 % (" ".join(SkippedArchList
), " ".join(self
.Platform
.SupArchList
)))
278 self
.ArchList
= tuple(ArchList
)
280 # Validate build target
281 if self
.BuildTarget
not in self
.Platform
.BuildTargets
:
282 EdkLogger
.error("build", PARAMETER_INVALID
,
283 ExtraData
="Build target [%s] is not supported by the platform. [Valid target: %s]"
284 % (self
.BuildTarget
, " ".join(self
.Platform
.BuildTargets
)))
287 # parse FDF file to get PCDs in it, if any
289 self
.FdfFile
= self
.Platform
.FlashDefinition
293 EdkLogger
.info('%-16s = %s' % ("Architecture(s)", ' '.join(self
.ArchList
)))
294 EdkLogger
.info('%-16s = %s' % ("Build target", self
.BuildTarget
))
295 EdkLogger
.info('%-16s = %s' % ("Toolchain",self
.ToolChain
))
297 EdkLogger
.info('\n%-24s = %s' % ("Active Platform", self
.Platform
))
299 EdkLogger
.info('%-24s = %s' % ("Active Module", BuildModule
))
302 EdkLogger
.info('%-24s = %s' % ("Flash Image Definition", self
.FdfFile
))
304 EdkLogger
.verbose("\nFLASH_DEFINITION = %s" % self
.FdfFile
)
307 Progress
.Start("\nProcessing meta-data")
311 # Mark now build in AutoGen Phase
313 GlobalData
.gAutoGenPhase
= True
314 Fdf
= FdfParser(self
.FdfFile
.Path
)
316 GlobalData
.gFdfParser
= Fdf
317 GlobalData
.gAutoGenPhase
= False
318 PcdSet
= Fdf
.Profile
.PcdDict
319 ModuleList
= Fdf
.Profile
.InfList
320 self
.FdfProfile
= Fdf
.Profile
321 for fvname
in self
.FvTargetList
:
322 if fvname
.upper() not in self
.FdfProfile
.FvDict
:
323 EdkLogger
.error("build", OPTION_VALUE_INVALID
,
324 "No such an FV in FDF file: %s" % fvname
)
328 self
.FdfProfile
= None
329 if self
.FdTargetList
:
330 EdkLogger
.info("No flash definition file found. FD [%s] will be ignored." % " ".join(self
.FdTargetList
))
331 self
.FdTargetList
= []
332 if self
.FvTargetList
:
333 EdkLogger
.info("No flash definition file found. FV [%s] will be ignored." % " ".join(self
.FvTargetList
))
334 self
.FvTargetList
= []
335 if self
.CapTargetList
:
336 EdkLogger
.info("No flash definition file found. Capsule [%s] will be ignored." % " ".join(self
.CapTargetList
))
337 self
.CapTargetList
= []
339 # apply SKU and inject PCDs from Flash Definition file
340 for Arch
in self
.ArchList
:
341 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
345 PGen
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
346 #Collect package set information from INF of FDF
348 for Inf
in ModuleList
:
349 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
350 if ModuleFile
in Platform
.Modules
:
352 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, Target
, Toolchain
]
353 PkgSet
.update(ModuleData
.Packages
)
354 Pkgs
= list(PkgSet
) + list(PGen
.PackageList
)
357 DecPcds
[Pcd
[0], Pcd
[1]] = Pkg
.Pcds
[Pcd
]
358 DecPcdsKey
.add((Pcd
[0], Pcd
[1], Pcd
[2]))
360 Platform
.SkuName
= self
.SkuId
361 for Name
, Guid
in PcdSet
:
362 if (Name
, Guid
) not in DecPcds
:
366 "PCD (%s.%s) used in FDF is not declared in DEC files." % (Guid
, Name
),
367 File
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][0],
368 Line
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][1]
371 # Check whether Dynamic or DynamicEx PCD used in FDF file. If used, build break and give a error message.
372 if (Name
, Guid
, TAB_PCDS_FIXED_AT_BUILD
) in DecPcdsKey \
373 or (Name
, Guid
, TAB_PCDS_PATCHABLE_IN_MODULE
) in DecPcdsKey \
374 or (Name
, Guid
, TAB_PCDS_FEATURE_FLAG
) in DecPcdsKey
:
375 Platform
.AddPcd(Name
, Guid
, PcdSet
[Name
, Guid
])
377 elif (Name
, Guid
, TAB_PCDS_DYNAMIC
) in DecPcdsKey
or (Name
, Guid
, TAB_PCDS_DYNAMIC_EX
) in DecPcdsKey
:
381 "Using Dynamic or DynamicEx type of PCD [%s.%s] in FDF file is not allowed." % (Guid
, Name
),
382 File
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][0],
383 Line
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
][1]
386 Pa
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
388 # Explicitly collect platform's dynamic PCDs
390 Pa
.CollectPlatformDynamicPcds()
391 Pa
.CollectFixedAtBuildPcds()
392 self
.AutoGenObjectList
.append(Pa
)
395 # Check PCDs token value conflict in each DEC file.
397 self
._CheckAllPcdsTokenValueConflict
()
400 # Check PCD type and definition between DSC and DEC
402 self
._CheckPcdDefineAndType
()
405 # self._CheckDuplicateInFV(Fdf)
407 self
._BuildDir
= None
409 self
._MakeFileDir
= None
410 self
._BuildCommand
= None
414 ## _CheckDuplicateInFV() method
416 # Check whether there is duplicate modules/files exist in FV section.
417 # The check base on the file GUID;
419 def _CheckDuplicateInFV(self
, Fdf
):
420 for Fv
in Fdf
.Profile
.FvDict
:
422 for FfsFile
in Fdf
.Profile
.FvDict
[Fv
].FfsList
:
423 if FfsFile
.InfFileName
and FfsFile
.NameGuid
== None:
428 for Pa
in self
.AutoGenObjectList
:
431 for Module
in Pa
.ModuleAutoGenList
:
432 if path
.normpath(Module
.MetaFile
.File
) == path
.normpath(FfsFile
.InfFileName
):
434 if not Module
.Guid
.upper() in _GuidDict
.keys():
435 _GuidDict
[Module
.Guid
.upper()] = FfsFile
438 EdkLogger
.error("build",
440 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s"%(FfsFile
.CurrentLineNum
,
441 FfsFile
.CurrentLineContent
,
442 _GuidDict
[Module
.Guid
.upper()].CurrentLineNum
,
443 _GuidDict
[Module
.Guid
.upper()].CurrentLineContent
,
444 Module
.Guid
.upper()),
445 ExtraData
=self
.FdfFile
)
447 # Some INF files not have entity in DSC file.
450 if FfsFile
.InfFileName
.find('$') == -1:
451 InfPath
= NormPath(FfsFile
.InfFileName
)
452 if not os
.path
.exists(InfPath
):
453 EdkLogger
.error('build', GENFDS_ERROR
, "Non-existant Module %s !" % (FfsFile
.InfFileName
))
455 PathClassObj
= PathClass(FfsFile
.InfFileName
, self
.WorkspaceDir
)
457 # Here we just need to get FILE_GUID from INF file, use 'COMMON' as ARCH attribute. and use
458 # BuildObject from one of AutoGenObjectList is enough.
460 InfObj
= self
.AutoGenObjectList
[0].BuildDatabase
.WorkspaceDb
.BuildObject
[PathClassObj
, 'COMMON', self
.BuildTarget
, self
.ToolChain
]
461 if not InfObj
.Guid
.upper() in _GuidDict
.keys():
462 _GuidDict
[InfObj
.Guid
.upper()] = FfsFile
464 EdkLogger
.error("build",
466 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s"%(FfsFile
.CurrentLineNum
,
467 FfsFile
.CurrentLineContent
,
468 _GuidDict
[InfObj
.Guid
.upper()].CurrentLineNum
,
469 _GuidDict
[InfObj
.Guid
.upper()].CurrentLineContent
,
470 InfObj
.Guid
.upper()),
471 ExtraData
=self
.FdfFile
)
474 if FfsFile
.NameGuid
!= None:
475 _CheckPCDAsGuidPattern
= re
.compile("^PCD\(.+\..+\)$")
478 # If the NameGuid reference a PCD name.
479 # The style must match: PCD(xxxx.yyy)
481 if _CheckPCDAsGuidPattern
.match(FfsFile
.NameGuid
):
483 # Replace the PCD value.
485 _PcdName
= FfsFile
.NameGuid
.lstrip("PCD(").rstrip(")")
487 for Pa
in self
.AutoGenObjectList
:
489 for PcdItem
in Pa
.AllPcdList
:
490 if (PcdItem
.TokenSpaceGuidCName
+ "." + PcdItem
.TokenCName
) == _PcdName
:
492 # First convert from CFormatGuid to GUID string
494 _PcdGuidString
= GuidStructureStringToGuidString(PcdItem
.DefaultValue
)
496 if not _PcdGuidString
:
498 # Then try Byte array.
500 _PcdGuidString
= GuidStructureByteArrayToGuidString(PcdItem
.DefaultValue
)
502 if not _PcdGuidString
:
504 # Not Byte array or CFormat GUID, raise error.
506 EdkLogger
.error("build",
508 "The format of PCD value is incorrect. PCD: %s , Value: %s\n"%(_PcdName
, PcdItem
.DefaultValue
),
509 ExtraData
=self
.FdfFile
)
511 if not _PcdGuidString
.upper() in _GuidDict
.keys():
512 _GuidDict
[_PcdGuidString
.upper()] = FfsFile
516 EdkLogger
.error("build",
518 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s"%(FfsFile
.CurrentLineNum
,
519 FfsFile
.CurrentLineContent
,
520 _GuidDict
[_PcdGuidString
.upper()].CurrentLineNum
,
521 _GuidDict
[_PcdGuidString
.upper()].CurrentLineContent
,
522 FfsFile
.NameGuid
.upper()),
523 ExtraData
=self
.FdfFile
)
525 if not FfsFile
.NameGuid
.upper() in _GuidDict
.keys():
526 _GuidDict
[FfsFile
.NameGuid
.upper()] = FfsFile
529 # Two raw file GUID conflict.
531 EdkLogger
.error("build",
533 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s"%(FfsFile
.CurrentLineNum
,
534 FfsFile
.CurrentLineContent
,
535 _GuidDict
[FfsFile
.NameGuid
.upper()].CurrentLineNum
,
536 _GuidDict
[FfsFile
.NameGuid
.upper()].CurrentLineContent
,
537 FfsFile
.NameGuid
.upper()),
538 ExtraData
=self
.FdfFile
)
541 def _CheckPcdDefineAndType(self
):
543 "FixedAtBuild", "PatchableInModule", "FeatureFlag",
544 "Dynamic", #"DynamicHii", "DynamicVpd",
545 "DynamicEx", # "DynamicExHii", "DynamicExVpd"
548 # This dict store PCDs which are not used by any modules with specified arches
550 for Pa
in self
.AutoGenObjectList
:
551 # Key of DSC's Pcds dictionary is PcdCName, TokenSpaceGuid
552 for Pcd
in Pa
.Platform
.Pcds
:
553 PcdType
= Pa
.Platform
.Pcds
[Pcd
].Type
555 # If no PCD type, this PCD comes from FDF
559 # Try to remove Hii and Vpd suffix
560 if PcdType
.startswith("DynamicEx"):
561 PcdType
= "DynamicEx"
562 elif PcdType
.startswith("Dynamic"):
565 for Package
in Pa
.PackageList
:
566 # Key of DEC's Pcds dictionary is PcdCName, TokenSpaceGuid, PcdType
567 if (Pcd
[0], Pcd
[1], PcdType
) in Package
.Pcds
:
569 for Type
in PcdTypeList
:
570 if (Pcd
[0], Pcd
[1], Type
) in Package
.Pcds
:
574 "Type [%s] of PCD [%s.%s] in DSC file doesn't match the type [%s] defined in DEC file." \
575 % (Pa
.Platform
.Pcds
[Pcd
].Type
, Pcd
[1], Pcd
[0], Type
),
580 UnusedPcd
.setdefault(Pcd
, []).append(Pa
.Arch
)
582 for Pcd
in UnusedPcd
:
585 "The PCD was not specified by any INF module in the platform for the given architecture.\n"
586 "\tPCD: [%s.%s]\n\tPlatform: [%s]\n\tArch: %s"
587 % (Pcd
[1], Pcd
[0], os
.path
.basename(str(self
.MetaFile
)), str(UnusedPcd
[Pcd
])),
592 return "%s [%s]" % (self
.MetaFile
, ", ".join(self
.ArchList
))
594 ## Return the directory to store FV files
596 if self
._FvDir
== None:
597 self
._FvDir
= path
.join(self
.BuildDir
, 'FV')
600 ## Return the directory to store all intermediate and final files built
601 def _GetBuildDir(self
):
602 return self
.AutoGenObjectList
[0].BuildDir
604 ## Return the build output directory platform specifies
605 def _GetOutputDir(self
):
606 return self
.Platform
.OutputDirectory
608 ## Return platform name
610 return self
.Platform
.PlatformName
612 ## Return meta-file GUID
614 return self
.Platform
.Guid
616 ## Return platform version
617 def _GetVersion(self
):
618 return self
.Platform
.Version
620 ## Return paths of tools
621 def _GetToolDefinition(self
):
622 return self
.AutoGenObjectList
[0].ToolDefinition
624 ## Return directory of platform makefile
626 # @retval string Makefile directory
628 def _GetMakeFileDir(self
):
629 if self
._MakeFileDir
== None:
630 self
._MakeFileDir
= self
.BuildDir
631 return self
._MakeFileDir
633 ## Return build command string
635 # @retval string Build command string
637 def _GetBuildCommand(self
):
638 if self
._BuildCommand
== None:
639 # BuildCommand should be all the same. So just get one from platform AutoGen
640 self
._BuildCommand
= self
.AutoGenObjectList
[0].BuildCommand
641 return self
._BuildCommand
643 ## Check the PCDs token value conflict in each DEC file.
645 # Will cause build break and raise error message while two PCDs conflict.
649 def _CheckAllPcdsTokenValueConflict(self
):
650 for Pa
in self
.AutoGenObjectList
:
651 for Package
in Pa
.PackageList
:
652 PcdList
= Package
.Pcds
.values()
653 PcdList
.sort(lambda x
, y
: cmp(x
.TokenValue
, y
.TokenValue
))
655 while (Count
< len(PcdList
) - 1) :
656 Item
= PcdList
[Count
]
657 ItemNext
= PcdList
[Count
+ 1]
659 # Make sure in the same token space the TokenValue should be unique
661 if (Item
.TokenValue
== ItemNext
.TokenValue
):
662 SameTokenValuePcdList
= []
663 SameTokenValuePcdList
.append(Item
)
664 SameTokenValuePcdList
.append(ItemNext
)
665 RemainPcdListLength
= len(PcdList
) - Count
- 2
666 for ValueSameCount
in range(RemainPcdListLength
):
667 if PcdList
[len(PcdList
) - RemainPcdListLength
+ ValueSameCount
].TokenValue
== Item
.TokenValue
:
668 SameTokenValuePcdList
.append(PcdList
[len(PcdList
) - RemainPcdListLength
+ ValueSameCount
])
672 # Sort same token value PCD list with TokenGuid and TokenCName
674 SameTokenValuePcdList
.sort(lambda x
, y
: cmp("%s.%s"%(x
.TokenSpaceGuidCName
, x
.TokenCName
), "%s.%s"%(y
.TokenSpaceGuidCName
, y
.TokenCName
)))
675 SameTokenValuePcdListCount
= 0
676 while (SameTokenValuePcdListCount
< len(SameTokenValuePcdList
) - 1):
677 TemListItem
= SameTokenValuePcdList
[SameTokenValuePcdListCount
]
678 TemListItemNext
= SameTokenValuePcdList
[SameTokenValuePcdListCount
+ 1]
680 if (TemListItem
.TokenSpaceGuidCName
== TemListItemNext
.TokenSpaceGuidCName
) and (TemListItem
.TokenCName
!= TemListItemNext
.TokenCName
):
684 "The TokenValue [%s] of PCD [%s.%s] is conflict with: [%s.%s] in %s"\
685 % (TemListItem
.TokenValue
, TemListItem
.TokenSpaceGuidCName
, TemListItem
.TokenCName
, TemListItemNext
.TokenSpaceGuidCName
, TemListItemNext
.TokenCName
, Package
),
688 SameTokenValuePcdListCount
+= 1
689 Count
+= SameTokenValuePcdListCount
692 PcdList
= Package
.Pcds
.values()
693 PcdList
.sort(lambda x
, y
: cmp("%s.%s"%(x
.TokenSpaceGuidCName
, x
.TokenCName
), "%s.%s"%(y
.TokenSpaceGuidCName
, y
.TokenCName
)))
695 while (Count
< len(PcdList
) - 1) :
696 Item
= PcdList
[Count
]
697 ItemNext
= PcdList
[Count
+ 1]
699 # Check PCDs with same TokenSpaceGuidCName.TokenCName have same token value as well.
701 if (Item
.TokenSpaceGuidCName
== ItemNext
.TokenSpaceGuidCName
) and (Item
.TokenCName
== ItemNext
.TokenCName
) and (Item
.TokenValue
!= ItemNext
.TokenValue
):
705 "The TokenValue [%s] of PCD [%s.%s] in %s defined in two places should be same as well."\
706 % (Item
.TokenValue
, Item
.TokenSpaceGuidCName
, Item
.TokenCName
, Package
),
710 ## Generate fds command
711 def _GenFdsCommand(self
):
712 return (GenMake
.TopLevelMakefile(self
)._TEMPLATE
_.Replace(GenMake
.TopLevelMakefile(self
)._TemplateDict
)).strip()
714 ## Create makefile for the platform and modules in it
716 # @param CreateDepsMakeFile Flag indicating if the makefile for
717 # modules will be created as well
719 def CreateMakeFile(self
, CreateDepsMakeFile
=False):
720 if CreateDepsMakeFile
:
721 for Pa
in self
.AutoGenObjectList
:
722 Pa
.CreateMakeFile(CreateDepsMakeFile
)
724 ## Create autogen code for platform and modules
726 # Since there's no autogen code for platform, this method will do nothing
727 # if CreateModuleCodeFile is set to False.
729 # @param CreateDepsCodeFile Flag indicating if creating module's
730 # autogen code file or not
732 def CreateCodeFile(self
, CreateDepsCodeFile
=False):
733 if not CreateDepsCodeFile
:
735 for Pa
in self
.AutoGenObjectList
:
736 Pa
.CreateCodeFile(CreateDepsCodeFile
)
738 ## Create AsBuilt INF file the platform
740 def CreateAsBuiltInf(self
):
743 Name
= property(_GetName
)
744 Guid
= property(_GetGuid
)
745 Version
= property(_GetVersion
)
746 OutputDir
= property(_GetOutputDir
)
748 ToolDefinition
= property(_GetToolDefinition
) # toolcode : tool path
750 BuildDir
= property(_GetBuildDir
)
751 FvDir
= property(_GetFvDir
)
752 MakeFileDir
= property(_GetMakeFileDir
)
753 BuildCommand
= property(_GetBuildCommand
)
754 GenFdsCommand
= property(_GenFdsCommand
)
756 ## AutoGen class for platform
758 # PlatformAutoGen class will process the original information in platform
759 # file in order to generate makefile for platform.
761 class PlatformAutoGen(AutoGen
):
763 # Used to store all PCDs for both PEI and DXE phase, in order to generate
764 # correct PCD database
767 _NonDynaPcdList_
= []
770 # The priority list while override build option
772 PrioList
= {"0x11111" : 16, # TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE (Highest)
773 "0x01111" : 15, # ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
774 "0x10111" : 14, # TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE
775 "0x00111" : 13, # ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE
776 "0x11011" : 12, # TARGET_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
777 "0x01011" : 11, # ******_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
778 "0x10011" : 10, # TARGET_*********_****_COMMANDTYPE_ATTRIBUTE
779 "0x00011" : 9, # ******_*********_****_COMMANDTYPE_ATTRIBUTE
780 "0x11101" : 8, # TARGET_TOOLCHAIN_ARCH_***********_ATTRIBUTE
781 "0x01101" : 7, # ******_TOOLCHAIN_ARCH_***********_ATTRIBUTE
782 "0x10101" : 6, # TARGET_*********_ARCH_***********_ATTRIBUTE
783 "0x00101" : 5, # ******_*********_ARCH_***********_ATTRIBUTE
784 "0x11001" : 4, # TARGET_TOOLCHAIN_****_***********_ATTRIBUTE
785 "0x01001" : 3, # ******_TOOLCHAIN_****_***********_ATTRIBUTE
786 "0x10001" : 2, # TARGET_*********_****_***********_ATTRIBUTE
787 "0x00001" : 1} # ******_*********_****_***********_ATTRIBUTE (Lowest)
789 ## The real constructor of PlatformAutoGen
791 # This method is not supposed to be called by users of PlatformAutoGen. It's
792 # only used by factory method __new__() to do real initialization work for an
793 # object of PlatformAutoGen
795 # @param Workspace WorkspaceAutoGen object
796 # @param PlatformFile Platform file (DSC file)
797 # @param Target Build target (DEBUG, RELEASE)
798 # @param Toolchain Name of tool chain
799 # @param Arch arch of the platform supports
801 def _Init(self
, Workspace
, PlatformFile
, Target
, Toolchain
, Arch
):
802 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen platform [%s] [%s]" % (PlatformFile
, Arch
))
803 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (PlatformFile
, Arch
, Toolchain
, Target
)
805 self
.MetaFile
= PlatformFile
806 self
.Workspace
= Workspace
807 self
.WorkspaceDir
= Workspace
.WorkspaceDir
808 self
.ToolChain
= Toolchain
809 self
.BuildTarget
= Target
811 self
.SourceDir
= PlatformFile
.SubDir
812 self
.SourceOverrideDir
= None
813 self
.FdTargetList
= self
.Workspace
.FdTargetList
814 self
.FvTargetList
= self
.Workspace
.FvTargetList
816 # get the original module/package/platform objects
817 self
.BuildDatabase
= Workspace
.BuildDatabase
819 # flag indicating if the makefile/C-code file has been created or not
820 self
.IsMakeFileCreated
= False
821 self
.IsCodeFileCreated
= False
823 self
._Platform
= None
828 self
._BuildRule
= None
829 self
._SourceDir
= None
830 self
._BuildDir
= None
831 self
._OutputDir
= None
833 self
._MakeFileDir
= None
836 self
._PcdTokenNumber
= None # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
837 self
._DynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
838 self
._NonDynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
839 self
._NonDynamicPcdDict
= {}
841 self
._ToolDefinitions
= None
842 self
._ToolDefFile
= None # toolcode : tool path
843 self
._ToolChainFamily
= None
844 self
._BuildRuleFamily
= None
845 self
._BuildOption
= None # toolcode : option
846 self
._EdkBuildOption
= None # edktoolcode : option
847 self
._EdkIIBuildOption
= None # edkiitoolcode : option
848 self
._PackageList
= None
849 self
._ModuleAutoGenList
= None
850 self
._LibraryAutoGenList
= None
851 self
._BuildCommand
= None
852 self
._AsBuildInfList
= []
853 self
._AsBuildModuleList
= []
854 if GlobalData
.gFdfParser
!= None:
855 self
._AsBuildInfList
= GlobalData
.gFdfParser
.Profile
.InfList
856 for Inf
in self
._AsBuildInfList
:
857 InfClass
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, self
.Arch
)
858 M
= self
.BuildDatabase
[InfClass
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
859 if not M
.IsSupportedArch
:
861 self
._AsBuildModuleList
.append(InfClass
)
862 # get library/modules for build
863 self
.LibraryBuildDirectoryList
= []
864 self
.ModuleBuildDirectoryList
= []
868 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
870 ## Create autogen code for platform and modules
872 # Since there's no autogen code for platform, this method will do nothing
873 # if CreateModuleCodeFile is set to False.
875 # @param CreateModuleCodeFile Flag indicating if creating module's
876 # autogen code file or not
878 def CreateCodeFile(self
, CreateModuleCodeFile
=False):
879 # only module has code to be greated, so do nothing if CreateModuleCodeFile is False
880 if self
.IsCodeFileCreated
or not CreateModuleCodeFile
:
883 for Ma
in self
.ModuleAutoGenList
:
884 Ma
.CreateCodeFile(True)
886 # don't do this twice
887 self
.IsCodeFileCreated
= True
889 ## Generate Fds Command
890 def _GenFdsCommand(self
):
891 return self
.Workspace
.GenFdsCommand
893 ## Create makefile for the platform and mdoules in it
895 # @param CreateModuleMakeFile Flag indicating if the makefile for
896 # modules will be created as well
898 def CreateMakeFile(self
, CreateModuleMakeFile
=False):
899 if CreateModuleMakeFile
:
900 for ModuleFile
in self
.Platform
.Modules
:
901 Ma
= ModuleAutoGen(self
.Workspace
, ModuleFile
, self
.BuildTarget
,
902 self
.ToolChain
, self
.Arch
, self
.MetaFile
)
903 Ma
.CreateMakeFile(True)
904 #Ma.CreateAsBuiltInf()
906 # no need to create makefile for the platform more than once
907 if self
.IsMakeFileCreated
:
910 # create library/module build dirs for platform
911 Makefile
= GenMake
.PlatformMakefile(self
)
912 self
.LibraryBuildDirectoryList
= Makefile
.GetLibraryBuildDirectoryList()
913 self
.ModuleBuildDirectoryList
= Makefile
.GetModuleBuildDirectoryList()
915 self
.IsMakeFileCreated
= True
917 ## Deal with Shared FixedAtBuild Pcds
919 def CollectFixedAtBuildPcds(self
):
920 for LibAuto
in self
.LibraryAutoGenList
:
921 FixedAtBuildPcds
= {}
922 ShareFixedAtBuildPcdsSameValue
= {}
923 for Module
in LibAuto
._ReferenceModules
:
924 for Pcd
in Module
.FixedAtBuildPcds
+ LibAuto
.FixedAtBuildPcds
:
925 key
= ".".join((Pcd
.TokenSpaceGuidCName
,Pcd
.TokenCName
))
926 if key
not in FixedAtBuildPcds
:
927 ShareFixedAtBuildPcdsSameValue
[key
] = True
928 FixedAtBuildPcds
[key
] = Pcd
.DefaultValue
930 if FixedAtBuildPcds
[key
] != Pcd
.DefaultValue
:
931 ShareFixedAtBuildPcdsSameValue
[key
] = False
932 for Pcd
in LibAuto
.FixedAtBuildPcds
:
933 key
= ".".join((Pcd
.TokenSpaceGuidCName
,Pcd
.TokenCName
))
934 if (Pcd
.TokenCName
,Pcd
.TokenSpaceGuidCName
) not in self
.NonDynamicPcdDict
:
937 DscPcd
= self
.NonDynamicPcdDict
[(Pcd
.TokenCName
,Pcd
.TokenSpaceGuidCName
)]
938 if DscPcd
.Type
!= "FixedAtBuild":
940 if key
in ShareFixedAtBuildPcdsSameValue
and ShareFixedAtBuildPcdsSameValue
[key
]:
941 LibAuto
.ConstPcd
[key
] = Pcd
.DefaultValue
943 ## Collect dynamic PCDs
945 # Gather dynamic PCDs list from each module and their settings from platform
946 # This interface should be invoked explicitly when platform action is created.
948 def CollectPlatformDynamicPcds(self
):
949 # for gathering error information
950 NoDatumTypePcdList
= set()
954 for InfName
in self
._AsBuildInfList
:
955 InfName
= os
.path
.join(self
.WorkspaceDir
, InfName
)
956 FdfModuleList
.append(os
.path
.normpath(InfName
))
957 for F
in self
.Platform
.Modules
.keys():
958 M
= ModuleAutoGen(self
.Workspace
, F
, self
.BuildTarget
, self
.ToolChain
, self
.Arch
, self
.MetaFile
)
959 #GuidValue.update(M.Guids)
961 self
.Platform
.Modules
[F
].M
= M
963 for PcdFromModule
in M
.ModulePcdList
+M
.LibraryPcdList
:
964 # make sure that the "VOID*" kind of datum has MaxDatumSize set
965 if PcdFromModule
.DatumType
== "VOID*" and PcdFromModule
.MaxDatumSize
in [None, '']:
966 NoDatumTypePcdList
.add("%s.%s [%s]" % (PcdFromModule
.TokenSpaceGuidCName
, PcdFromModule
.TokenCName
, F
))
968 # Check the PCD from Binary INF or Source INF
969 if M
.IsBinaryModule
== True:
970 PcdFromModule
.IsFromBinaryInf
= True
972 # Check the PCD from DSC or not
973 if (PcdFromModule
.TokenCName
, PcdFromModule
.TokenSpaceGuidCName
) in self
.Platform
.Pcds
.keys():
974 PcdFromModule
.IsFromDsc
= True
976 PcdFromModule
.IsFromDsc
= False
977 if PcdFromModule
.Type
in GenC
.gDynamicPcd
or PcdFromModule
.Type
in GenC
.gDynamicExPcd
:
978 if F
.Path
not in FdfModuleList
:
979 # If one of the Source built modules listed in the DSC is not listed
980 # in FDF modules, and the INF lists a PCD can only use the PcdsDynamic
981 # access method (it is only listed in the DEC file that declares the
982 # PCD as PcdsDynamic), then build tool will report warning message
983 # notify the PI that they are attempting to build a module that must
984 # be included in a flash image in order to be functional. These Dynamic
985 # PCD will not be added into the Database unless it is used by other
986 # modules that are included in the FDF file.
987 if PcdFromModule
.Type
in GenC
.gDynamicPcd
and \
988 PcdFromModule
.IsFromBinaryInf
== False:
989 # Print warning message to let the developer make a determine.
990 if PcdFromModule
not in PcdNotInDb
:
991 PcdNotInDb
.append(PcdFromModule
)
993 # If one of the Source built modules listed in the DSC is not listed in
994 # FDF modules, and the INF lists a PCD can only use the PcdsDynamicEx
995 # access method (it is only listed in the DEC file that declares the
996 # PCD as PcdsDynamicEx), then DO NOT break the build; DO NOT add the
997 # PCD to the Platform's PCD Database.
998 if PcdFromModule
.Type
in GenC
.gDynamicExPcd
:
999 if PcdFromModule
not in PcdNotInDb
:
1000 PcdNotInDb
.append(PcdFromModule
)
1003 # If a dynamic PCD used by a PEM module/PEI module & DXE module,
1004 # it should be stored in Pcd PEI database, If a dynamic only
1005 # used by DXE module, it should be stored in DXE PCD database.
1006 # The default Phase is DXE
1008 if M
.ModuleType
in ["PEIM", "PEI_CORE"]:
1009 PcdFromModule
.Phase
= "PEI"
1010 if PcdFromModule
not in self
._DynaPcdList
_:
1011 self
._DynaPcdList
_.append(PcdFromModule
)
1012 elif PcdFromModule
.Phase
== 'PEI':
1013 # overwrite any the same PCD existing, if Phase is PEI
1014 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1015 self
._DynaPcdList
_[Index
] = PcdFromModule
1016 elif PcdFromModule
not in self
._NonDynaPcdList
_:
1017 self
._NonDynaPcdList
_.append(PcdFromModule
)
1018 elif PcdFromModule
in self
._NonDynaPcdList
_ and PcdFromModule
.IsFromBinaryInf
== True:
1019 Index
= self
._NonDynaPcdList
_.index(PcdFromModule
)
1020 if self
._NonDynaPcdList
_[Index
].IsFromBinaryInf
== False:
1021 #The PCD from Binary INF will override the same one from source INF
1022 self
._NonDynaPcdList
_.remove (self
._NonDynaPcdList
_[Index
])
1023 PcdFromModule
.Pending
= False
1024 self
._NonDynaPcdList
_.append (PcdFromModule
)
1025 # Parse the DynamicEx PCD from the AsBuild INF module list of FDF.
1027 for ModuleInf
in self
.Platform
.Modules
.keys():
1028 DscModuleList
.append (os
.path
.normpath(ModuleInf
.Path
))
1029 # add the PCD from modules that listed in FDF but not in DSC to Database
1030 for InfName
in FdfModuleList
:
1031 if InfName
not in DscModuleList
:
1032 InfClass
= PathClass(InfName
)
1033 M
= self
.BuildDatabase
[InfClass
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1034 # If a module INF in FDF but not in current arch's DSC module list, it must be module (either binary or source)
1035 # for different Arch. PCDs in source module for different Arch is already added before, so skip the source module here.
1036 # For binary module, if in current arch, we need to list the PCDs into database.
1037 if not M
.IsSupportedArch
:
1039 # Override the module PCD setting by platform setting
1040 ModulePcdList
= self
.ApplyPcdSetting(M
, M
.Pcds
)
1041 for PcdFromModule
in ModulePcdList
:
1042 PcdFromModule
.IsFromBinaryInf
= True
1043 PcdFromModule
.IsFromDsc
= False
1044 # Only allow the DynamicEx and Patchable PCD in AsBuild INF
1045 if PcdFromModule
.Type
not in GenC
.gDynamicExPcd
and PcdFromModule
.Type
not in TAB_PCDS_PATCHABLE_IN_MODULE
:
1046 EdkLogger
.error("build", AUTOGEN_ERROR
, "PCD setting error",
1048 ExtraData
="\n\tExisted %s PCD %s in:\n\t\t%s\n"
1049 % (PcdFromModule
.Type
, PcdFromModule
.TokenCName
, InfName
))
1050 # make sure that the "VOID*" kind of datum has MaxDatumSize set
1051 if PcdFromModule
.DatumType
== "VOID*" and PcdFromModule
.MaxDatumSize
in [None, '']:
1052 NoDatumTypePcdList
.add("%s.%s [%s]" % (PcdFromModule
.TokenSpaceGuidCName
, PcdFromModule
.TokenCName
, InfName
))
1053 if M
.ModuleType
in ["PEIM", "PEI_CORE"]:
1054 PcdFromModule
.Phase
= "PEI"
1055 if PcdFromModule
not in self
._DynaPcdList
_ and PcdFromModule
.Type
in GenC
.gDynamicExPcd
:
1056 self
._DynaPcdList
_.append(PcdFromModule
)
1057 elif PcdFromModule
not in self
._NonDynaPcdList
_ and PcdFromModule
.Type
in TAB_PCDS_PATCHABLE_IN_MODULE
:
1058 self
._NonDynaPcdList
_.append(PcdFromModule
)
1059 if PcdFromModule
in self
._DynaPcdList
_ and PcdFromModule
.Phase
== 'PEI' and PcdFromModule
.Type
in GenC
.gDynamicExPcd
:
1060 # Overwrite the phase of any the same PCD existing, if Phase is PEI.
1061 # It is to solve the case that a dynamic PCD used by a PEM module/PEI
1062 # module & DXE module at a same time.
1063 # Overwrite the type of the PCDs in source INF by the type of AsBuild
1064 # INF file as DynamicEx.
1065 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1066 self
._DynaPcdList
_[Index
].Phase
= PcdFromModule
.Phase
1067 self
._DynaPcdList
_[Index
].Type
= PcdFromModule
.Type
1068 for PcdFromModule
in self
._NonDynaPcdList
_:
1069 # If a PCD is not listed in the DSC file, but binary INF files used by
1070 # this platform all (that use this PCD) list the PCD in a [PatchPcds]
1071 # section, AND all source INF files used by this platform the build
1072 # that use the PCD list the PCD in either a [Pcds] or [PatchPcds]
1073 # section, then the tools must NOT add the PCD to the Platform's PCD
1074 # Database; the build must assign the access method for this PCD as
1075 # PcdsPatchableInModule.
1076 if PcdFromModule
not in self
._DynaPcdList
_:
1078 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1079 if PcdFromModule
.IsFromDsc
== False and \
1080 PcdFromModule
.Type
in TAB_PCDS_PATCHABLE_IN_MODULE
and \
1081 PcdFromModule
.IsFromBinaryInf
== True and \
1082 self
._DynaPcdList
_[Index
].IsFromBinaryInf
== False:
1083 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1084 self
._DynaPcdList
_.remove (self
._DynaPcdList
_[Index
])
1086 # print out error information and break the build, if error found
1087 if len(NoDatumTypePcdList
) > 0:
1088 NoDatumTypePcdListString
= "\n\t\t".join(NoDatumTypePcdList
)
1089 EdkLogger
.error("build", AUTOGEN_ERROR
, "PCD setting error",
1091 ExtraData
="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"
1092 % NoDatumTypePcdListString
)
1093 self
._NonDynamicPcdList
= self
._NonDynaPcdList
_
1094 self
._DynamicPcdList
= self
._DynaPcdList
_
1096 # Sort dynamic PCD list to:
1097 # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should
1098 # try to be put header of dynamicd List
1099 # 2) If PCD is HII type, the PCD item should be put after unicode type PCD
1101 # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.
1103 UnicodePcdArray
= []
1107 VpdFile
= VpdInfoFile
.VpdInfoFile()
1108 NeedProcessVpdMapFile
= False
1110 if (self
.Workspace
.ArchList
[-1] == self
.Arch
):
1111 for Pcd
in self
._DynamicPcdList
:
1112 # just pick the a value to determine whether is unicode string type
1113 Sku
= Pcd
.SkuInfoList
[Pcd
.SkuInfoList
.keys()[0]]
1114 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1116 PcdValue
= Sku
.DefaultValue
1117 if Pcd
.DatumType
== 'VOID*' and PcdValue
.startswith("L"):
1118 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
1119 UnicodePcdArray
.append(Pcd
)
1120 elif len(Sku
.VariableName
) > 0:
1121 # if found HII type PCD then insert to right of UnicodeIndex
1122 HiiPcdArray
.append(Pcd
)
1124 OtherPcdArray
.append(Pcd
)
1125 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
1126 VpdPcdDict
[(Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
)] = Pcd
1128 PlatformPcds
= self
.Platform
.Pcds
.keys()
1131 # Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.
1133 for PcdKey
in PlatformPcds
:
1134 Pcd
= self
.Platform
.Pcds
[PcdKey
]
1135 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
] and \
1136 PcdKey
in VpdPcdDict
:
1137 Pcd
= VpdPcdDict
[PcdKey
]
1138 for (SkuName
,Sku
) in Pcd
.SkuInfoList
.items():
1139 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1140 VpdFile
.Add(Pcd
, Sku
.VpdOffset
)
1141 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
1142 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== "*":
1143 NeedProcessVpdMapFile
= True
1144 if self
.Platform
.VpdToolGuid
== None or self
.Platform
.VpdToolGuid
== '':
1145 EdkLogger
.error("Build", FILE_NOT_FOUND
, \
1146 "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.")
1150 # Fix the PCDs define in VPD PCD section that never referenced by module.
1151 # An example is PCD for signature usage.
1153 for DscPcd
in PlatformPcds
:
1154 DscPcdEntry
= self
.Platform
.Pcds
[DscPcd
]
1155 if DscPcdEntry
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
1156 if not (self
.Platform
.VpdToolGuid
== None or self
.Platform
.VpdToolGuid
== ''):
1158 for VpdPcd
in VpdFile
._VpdArray
.keys():
1159 # This PCD has been referenced by module
1160 if (VpdPcd
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
1161 (VpdPcd
.TokenCName
== DscPcdEntry
.TokenCName
):
1164 # Not found, it should be signature
1166 # just pick the a value to determine whether is unicode string type
1167 for (SkuName
,Sku
) in DscPcdEntry
.SkuInfoList
.items():
1168 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1170 # Need to iterate DEC pcd information to get the value & datumtype
1171 for eachDec
in self
.PackageList
:
1172 for DecPcd
in eachDec
.Pcds
:
1173 DecPcdEntry
= eachDec
.Pcds
[DecPcd
]
1174 if (DecPcdEntry
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
1175 (DecPcdEntry
.TokenCName
== DscPcdEntry
.TokenCName
):
1176 # Print warning message to let the developer make a determine.
1177 EdkLogger
.warn("build", "Unreferenced vpd pcd used!",
1178 File
=self
.MetaFile
, \
1179 ExtraData
= "PCD: %s.%s used in the DSC file %s is unreferenced." \
1180 %(DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
, self
.Platform
.MetaFile
.Path
))
1182 DscPcdEntry
.DatumType
= DecPcdEntry
.DatumType
1183 DscPcdEntry
.DefaultValue
= DecPcdEntry
.DefaultValue
1184 DscPcdEntry
.TokenValue
= DecPcdEntry
.TokenValue
1185 DscPcdEntry
.TokenSpaceGuidValue
= eachDec
.Guids
[DecPcdEntry
.TokenSpaceGuidCName
]
1186 # Only fix the value while no value provided in DSC file.
1187 if (Sku
.DefaultValue
== "" or Sku
.DefaultValue
==None):
1188 DscPcdEntry
.SkuInfoList
[DscPcdEntry
.SkuInfoList
.keys()[0]].DefaultValue
= DecPcdEntry
.DefaultValue
1190 if DscPcdEntry
not in self
._DynamicPcdList
:
1191 self
._DynamicPcdList
.append(DscPcdEntry
)
1192 # Sku = DscPcdEntry.SkuInfoList[DscPcdEntry.SkuInfoList.keys()[0]]
1193 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1194 PcdValue
= Sku
.DefaultValue
1195 VpdFile
.Add(DscPcdEntry
, Sku
.VpdOffset
)
1196 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== "*":
1197 NeedProcessVpdMapFile
= True
1198 if DscPcdEntry
.DatumType
== 'VOID*' and PcdValue
.startswith("L"):
1199 UnicodePcdArray
.append(DscPcdEntry
)
1200 elif len(Sku
.VariableName
) > 0:
1201 HiiPcdArray
.append(DscPcdEntry
)
1203 OtherPcdArray
.append(DscPcdEntry
)
1205 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
1209 if (self
.Platform
.FlashDefinition
== None or self
.Platform
.FlashDefinition
== '') and \
1210 VpdFile
.GetCount() != 0:
1211 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
,
1212 "Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD." % str(self
.Platform
.MetaFile
))
1214 if VpdFile
.GetCount() != 0:
1215 DscTimeStamp
= self
.Platform
.MetaFile
.TimeStamp
1216 FvPath
= os
.path
.join(self
.BuildDir
, "FV")
1217 if not os
.path
.exists(FvPath
):
1221 EdkLogger
.error("build", FILE_WRITE_FAILURE
, "Fail to create FV folder under %s" % self
.BuildDir
)
1224 VpdFilePath
= os
.path
.join(FvPath
, "%s.txt" % self
.Platform
.VpdToolGuid
)
1227 if not os
.path
.exists(VpdFilePath
) or os
.path
.getmtime(VpdFilePath
) < DscTimeStamp
:
1228 VpdFile
.Write(VpdFilePath
)
1230 # retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.
1232 for ToolDef
in self
.ToolDefinition
.values():
1233 if ToolDef
.has_key("GUID") and ToolDef
["GUID"] == self
.Platform
.VpdToolGuid
:
1234 if not ToolDef
.has_key("PATH"):
1235 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
, "PATH attribute was not provided for BPDG guid tool %s in tools_def.txt" % self
.Platform
.VpdToolGuid
)
1236 BPDGToolName
= ToolDef
["PATH"]
1238 # Call third party GUID BPDG tool.
1239 if BPDGToolName
!= None:
1240 VpdInfoFile
.CallExtenalBPDGTool(BPDGToolName
, VpdFilePath
)
1242 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.")
1244 # Process VPD map file generated by third party BPDG tool
1245 if NeedProcessVpdMapFile
:
1246 VpdMapFilePath
= os
.path
.join(self
.BuildDir
, "FV", "%s.map" % self
.Platform
.VpdToolGuid
)
1247 if os
.path
.exists(VpdMapFilePath
):
1248 VpdFile
.Read(VpdMapFilePath
)
1251 for Pcd
in self
._DynamicPcdList
:
1252 # just pick the a value to determine whether is unicode string type
1254 for (SkuName
,Sku
) in Pcd
.SkuInfoList
.items():
1255 if Sku
.VpdOffset
== "*":
1256 Sku
.VpdOffset
= VpdFile
.GetOffset(Pcd
)[i
].strip()
1259 EdkLogger
.error("build", FILE_READ_FAILURE
, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath
)
1261 # Delete the DynamicPcdList At the last time enter into this function
1262 del self
._DynamicPcdList
[:]
1263 self
._DynamicPcdList
.extend(UnicodePcdArray
)
1264 self
._DynamicPcdList
.extend(HiiPcdArray
)
1265 self
._DynamicPcdList
.extend(OtherPcdArray
)
1266 self
.AllPcdList
= self
._NonDynamicPcdList
+ self
._DynamicPcdList
1268 ## Return the platform build data object
1269 def _GetPlatform(self
):
1270 if self
._Platform
== None:
1271 self
._Platform
= self
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1272 return self
._Platform
1274 ## Return platform name
1276 return self
.Platform
.PlatformName
1278 ## Return the meta file GUID
1280 return self
.Platform
.Guid
1282 ## Return the platform version
1283 def _GetVersion(self
):
1284 return self
.Platform
.Version
1286 ## Return the FDF file name
1287 def _GetFdfFile(self
):
1288 if self
._FdfFile
== None:
1289 if self
.Workspace
.FdfFile
!= "":
1290 self
._FdfFile
= path
.join(self
.WorkspaceDir
, self
.Workspace
.FdfFile
)
1293 return self
._FdfFile
1295 ## Return the build output directory platform specifies
1296 def _GetOutputDir(self
):
1297 return self
.Platform
.OutputDirectory
1299 ## Return the directory to store all intermediate and final files built
1300 def _GetBuildDir(self
):
1301 if self
._BuildDir
== None:
1302 if os
.path
.isabs(self
.OutputDir
):
1303 self
._BuildDir
= path
.join(
1304 path
.abspath(self
.OutputDir
),
1305 self
.BuildTarget
+ "_" + self
.ToolChain
,
1308 self
._BuildDir
= path
.join(
1311 self
.BuildTarget
+ "_" + self
.ToolChain
,
1313 return self
._BuildDir
1315 ## Return directory of platform makefile
1317 # @retval string Makefile directory
1319 def _GetMakeFileDir(self
):
1320 if self
._MakeFileDir
== None:
1321 self
._MakeFileDir
= path
.join(self
.BuildDir
, self
.Arch
)
1322 return self
._MakeFileDir
1324 ## Return build command string
1326 # @retval string Build command string
1328 def _GetBuildCommand(self
):
1329 if self
._BuildCommand
== None:
1330 self
._BuildCommand
= []
1331 if "MAKE" in self
.ToolDefinition
and "PATH" in self
.ToolDefinition
["MAKE"]:
1332 self
._BuildCommand
+= SplitOption(self
.ToolDefinition
["MAKE"]["PATH"])
1333 if "FLAGS" in self
.ToolDefinition
["MAKE"]:
1334 NewOption
= self
.ToolDefinition
["MAKE"]["FLAGS"].strip()
1336 self
._BuildCommand
+= SplitOption(NewOption
)
1337 return self
._BuildCommand
1339 ## Get tool chain definition
1341 # Get each tool defition for given tool chain from tools_def.txt and platform
1343 def _GetToolDefinition(self
):
1344 if self
._ToolDefinitions
== None:
1345 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDictionary
1346 if TAB_TOD_DEFINES_COMMAND_TYPE
not in self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
:
1347 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
, "No tools found in configuration",
1348 ExtraData
="[%s]" % self
.MetaFile
)
1349 self
._ToolDefinitions
= {}
1351 for Def
in ToolDefinition
:
1352 Target
, Tag
, Arch
, Tool
, Attr
= Def
.split("_")
1353 if Target
!= self
.BuildTarget
or Tag
!= self
.ToolChain
or Arch
!= self
.Arch
:
1356 Value
= ToolDefinition
[Def
]
1357 # don't record the DLL
1359 DllPathList
.add(Value
)
1362 if Tool
not in self
._ToolDefinitions
:
1363 self
._ToolDefinitions
[Tool
] = {}
1364 self
._ToolDefinitions
[Tool
][Attr
] = Value
1368 if GlobalData
.gOptions
.SilentMode
and "MAKE" in self
._ToolDefinitions
:
1369 if "FLAGS" not in self
._ToolDefinitions
["MAKE"]:
1370 self
._ToolDefinitions
["MAKE"]["FLAGS"] = ""
1371 self
._ToolDefinitions
["MAKE"]["FLAGS"] += " -s"
1373 for Tool
in self
._ToolDefinitions
:
1374 for Attr
in self
._ToolDefinitions
[Tool
]:
1375 Value
= self
._ToolDefinitions
[Tool
][Attr
]
1376 if Tool
in self
.BuildOption
and Attr
in self
.BuildOption
[Tool
]:
1377 # check if override is indicated
1378 if self
.BuildOption
[Tool
][Attr
].startswith('='):
1379 Value
= self
.BuildOption
[Tool
][Attr
][1:]
1381 Value
+= " " + self
.BuildOption
[Tool
][Attr
]
1384 # Don't put MAKE definition in the file
1388 ToolsDef
+= "%s = %s\n" % (Tool
, Value
)
1390 # Don't put MAKE definition in the file
1395 ToolsDef
+= "%s_%s = %s\n" % (Tool
, Attr
, Value
)
1398 SaveFileOnChange(self
.ToolDefinitionFile
, ToolsDef
)
1399 for DllPath
in DllPathList
:
1400 os
.environ
["PATH"] = DllPath
+ os
.pathsep
+ os
.environ
["PATH"]
1401 os
.environ
["MAKE_FLAGS"] = MakeFlags
1403 return self
._ToolDefinitions
1405 ## Return the paths of tools
1406 def _GetToolDefFile(self
):
1407 if self
._ToolDefFile
== None:
1408 self
._ToolDefFile
= os
.path
.join(self
.MakeFileDir
, "TOOLS_DEF." + self
.Arch
)
1409 return self
._ToolDefFile
1411 ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
1412 def _GetToolChainFamily(self
):
1413 if self
._ToolChainFamily
== None:
1414 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
1415 if TAB_TOD_DEFINES_FAMILY
not in ToolDefinition \
1416 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_FAMILY
] \
1417 or not ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]:
1418 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1420 self
._ToolChainFamily
= "MSFT"
1422 self
._ToolChainFamily
= ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]
1423 return self
._ToolChainFamily
1425 def _GetBuildRuleFamily(self
):
1426 if self
._BuildRuleFamily
== None:
1427 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
1428 if TAB_TOD_DEFINES_BUILDRULEFAMILY
not in ToolDefinition \
1429 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
] \
1430 or not ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]:
1431 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1433 self
._BuildRuleFamily
= "MSFT"
1435 self
._BuildRuleFamily
= ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]
1436 return self
._BuildRuleFamily
1438 ## Return the build options specific for all modules in this platform
1439 def _GetBuildOptions(self
):
1440 if self
._BuildOption
== None:
1441 self
._BuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
)
1442 return self
._BuildOption
1444 ## Return the build options specific for EDK modules in this platform
1445 def _GetEdkBuildOptions(self
):
1446 if self
._EdkBuildOption
== None:
1447 self
._EdkBuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDK_NAME
)
1448 return self
._EdkBuildOption
1450 ## Return the build options specific for EDKII modules in this platform
1451 def _GetEdkIIBuildOptions(self
):
1452 if self
._EdkIIBuildOption
== None:
1453 self
._EdkIIBuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDKII_NAME
)
1454 return self
._EdkIIBuildOption
1456 ## Parse build_rule.txt in Conf Directory.
1458 # @retval BuildRule object
1460 def _GetBuildRule(self
):
1461 if self
._BuildRule
== None:
1462 BuildRuleFile
= None
1463 if TAB_TAT_DEFINES_BUILD_RULE_CONF
in self
.Workspace
.TargetTxt
.TargetTxtDictionary
:
1464 BuildRuleFile
= self
.Workspace
.TargetTxt
.TargetTxtDictionary
[TAB_TAT_DEFINES_BUILD_RULE_CONF
]
1465 if BuildRuleFile
in [None, '']:
1466 BuildRuleFile
= gDefaultBuildRuleFile
1467 self
._BuildRule
= BuildRule(BuildRuleFile
)
1468 if self
._BuildRule
._FileVersion
== "":
1469 self
._BuildRule
._FileVersion
= AutoGenReqBuildRuleVerNum
1471 if self
._BuildRule
._FileVersion
< AutoGenReqBuildRuleVerNum
:
1472 # If Build Rule's version is less than the version number required by the tools, halting the build.
1473 EdkLogger
.error("build", AUTOGEN_ERROR
,
1474 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])"\
1475 % (self
._BuildRule
._FileVersion
, AutoGenReqBuildRuleVerNum
))
1477 return self
._BuildRule
1479 ## Summarize the packages used by modules in this platform
1480 def _GetPackageList(self
):
1481 if self
._PackageList
== None:
1482 self
._PackageList
= set()
1483 for La
in self
.LibraryAutoGenList
:
1484 self
._PackageList
.update(La
.DependentPackageList
)
1485 for Ma
in self
.ModuleAutoGenList
:
1486 self
._PackageList
.update(Ma
.DependentPackageList
)
1487 #Collect package set information from INF of FDF
1489 for ModuleFile
in self
._AsBuildModuleList
:
1490 if ModuleFile
in self
.Platform
.Modules
:
1492 ModuleData
= self
.BuildDatabase
[ModuleFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1493 PkgSet
.update(ModuleData
.Packages
)
1494 self
._PackageList
= list(self
._PackageList
) + list (PkgSet
)
1495 return self
._PackageList
1497 def _GetNonDynamicPcdDict(self
):
1498 if self
._NonDynamicPcdDict
:
1499 return self
._NonDynamicPcdDict
1500 for Pcd
in self
.NonDynamicPcdList
:
1501 self
._NonDynamicPcdDict
[(Pcd
.TokenCName
,Pcd
.TokenSpaceGuidCName
)] = Pcd
1502 return self
._NonDynamicPcdDict
1504 ## Get list of non-dynamic PCDs
1505 def _GetNonDynamicPcdList(self
):
1506 if self
._NonDynamicPcdList
== None:
1507 self
.CollectPlatformDynamicPcds()
1508 return self
._NonDynamicPcdList
1510 ## Get list of dynamic PCDs
1511 def _GetDynamicPcdList(self
):
1512 if self
._DynamicPcdList
== None:
1513 self
.CollectPlatformDynamicPcds()
1514 return self
._DynamicPcdList
1516 ## Generate Token Number for all PCD
1517 def _GetPcdTokenNumbers(self
):
1518 if self
._PcdTokenNumber
== None:
1519 self
._PcdTokenNumber
= sdict()
1522 # Make the Dynamic and DynamicEx PCD use within different TokenNumber area.
1526 # TokenNumber 0 ~ 10
1528 # TokeNumber 11 ~ 20
1530 for Pcd
in self
.DynamicPcdList
:
1531 if Pcd
.Phase
== "PEI":
1532 if Pcd
.Type
in ["Dynamic", "DynamicDefault", "DynamicVpd", "DynamicHii"]:
1533 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
1534 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1537 for Pcd
in self
.DynamicPcdList
:
1538 if Pcd
.Phase
== "PEI":
1539 if Pcd
.Type
in ["DynamicEx", "DynamicExDefault", "DynamicExVpd", "DynamicExHii"]:
1540 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
1541 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1544 for Pcd
in self
.DynamicPcdList
:
1545 if Pcd
.Phase
== "DXE":
1546 if Pcd
.Type
in ["Dynamic", "DynamicDefault", "DynamicVpd", "DynamicHii"]:
1547 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
1548 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1551 for Pcd
in self
.DynamicPcdList
:
1552 if Pcd
.Phase
== "DXE":
1553 if Pcd
.Type
in ["DynamicEx", "DynamicExDefault", "DynamicExVpd", "DynamicExHii"]:
1554 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
1555 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1558 for Pcd
in self
.NonDynamicPcdList
:
1559 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
1561 return self
._PcdTokenNumber
1563 ## Summarize ModuleAutoGen objects of all modules/libraries to be built for this platform
1564 def _GetAutoGenObjectList(self
):
1565 self
._ModuleAutoGenList
= []
1566 self
._LibraryAutoGenList
= []
1567 for ModuleFile
in self
.Platform
.Modules
:
1576 if Ma
not in self
._ModuleAutoGenList
:
1577 self
._ModuleAutoGenList
.append(Ma
)
1578 for La
in Ma
.LibraryAutoGenList
:
1579 if La
not in self
._LibraryAutoGenList
:
1580 self
._LibraryAutoGenList
.append(La
)
1581 if Ma
not in La
._ReferenceModules
:
1582 La
._ReferenceModules
.append(Ma
)
1584 ## Summarize ModuleAutoGen objects of all modules to be built for this platform
1585 def _GetModuleAutoGenList(self
):
1586 if self
._ModuleAutoGenList
== None:
1587 self
._GetAutoGenObjectList
()
1588 return self
._ModuleAutoGenList
1590 ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
1591 def _GetLibraryAutoGenList(self
):
1592 if self
._LibraryAutoGenList
== None:
1593 self
._GetAutoGenObjectList
()
1594 return self
._LibraryAutoGenList
1596 ## Test if a module is supported by the platform
1598 # An error will be raised directly if the module or its arch is not supported
1599 # by the platform or current configuration
1601 def ValidModule(self
, Module
):
1602 return Module
in self
.Platform
.Modules
or Module
in self
.Platform
.LibraryInstances \
1603 or Module
in self
._AsBuildModuleList
1605 ## Resolve the library classes in a module to library instances
1607 # This method will not only resolve library classes but also sort the library
1608 # instances according to the dependency-ship.
1610 # @param Module The module from which the library classes will be resolved
1612 # @retval library_list List of library instances sorted
1614 def ApplyLibraryInstance(self
, Module
):
1615 ModuleType
= Module
.ModuleType
1617 # for overridding library instances with module specific setting
1618 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
1620 # add forced library instances (specified under LibraryClasses sections)
1622 # If a module has a MODULE_TYPE of USER_DEFINED,
1623 # do not link in NULL library class instances from the global [LibraryClasses.*] sections.
1625 if Module
.ModuleType
!= SUP_MODULE_USER_DEFINED
:
1626 for LibraryClass
in self
.Platform
.LibraryClasses
.GetKeys():
1627 if LibraryClass
.startswith("NULL") and self
.Platform
.LibraryClasses
[LibraryClass
, Module
.ModuleType
]:
1628 Module
.LibraryClasses
[LibraryClass
] = self
.Platform
.LibraryClasses
[LibraryClass
, Module
.ModuleType
]
1630 # add forced library instances (specified in module overrides)
1631 for LibraryClass
in PlatformModule
.LibraryClasses
:
1632 if LibraryClass
.startswith("NULL"):
1633 Module
.LibraryClasses
[LibraryClass
] = PlatformModule
.LibraryClasses
[LibraryClass
]
1636 LibraryConsumerList
= [Module
]
1638 ConsumedByList
= sdict()
1639 LibraryInstance
= sdict()
1641 EdkLogger
.verbose("")
1642 EdkLogger
.verbose("Library instances of module [%s] [%s]:" % (str(Module
), self
.Arch
))
1643 while len(LibraryConsumerList
) > 0:
1644 M
= LibraryConsumerList
.pop()
1645 for LibraryClassName
in M
.LibraryClasses
:
1646 if LibraryClassName
not in LibraryInstance
:
1647 # override library instance for this module
1648 if LibraryClassName
in PlatformModule
.LibraryClasses
:
1649 LibraryPath
= PlatformModule
.LibraryClasses
[LibraryClassName
]
1651 LibraryPath
= self
.Platform
.LibraryClasses
[LibraryClassName
, ModuleType
]
1652 if LibraryPath
== None or LibraryPath
== "":
1653 LibraryPath
= M
.LibraryClasses
[LibraryClassName
]
1654 if LibraryPath
== None or LibraryPath
== "":
1655 EdkLogger
.error("build", RESOURCE_NOT_AVAILABLE
,
1656 "Instance of library class [%s] is not found" % LibraryClassName
,
1658 ExtraData
="in [%s] [%s]\n\tconsumed by module [%s]" % (str(M
), self
.Arch
, str(Module
)))
1660 LibraryModule
= self
.BuildDatabase
[LibraryPath
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1661 # for those forced library instance (NULL library), add a fake library class
1662 if LibraryClassName
.startswith("NULL"):
1663 LibraryModule
.LibraryClass
.append(LibraryClassObject(LibraryClassName
, [ModuleType
]))
1664 elif LibraryModule
.LibraryClass
== None \
1665 or len(LibraryModule
.LibraryClass
) == 0 \
1666 or (ModuleType
!= 'USER_DEFINED'
1667 and ModuleType
not in LibraryModule
.LibraryClass
[0].SupModList
):
1668 # only USER_DEFINED can link against any library instance despite of its SupModList
1669 EdkLogger
.error("build", OPTION_MISSING
,
1670 "Module type [%s] is not supported by library instance [%s]" \
1671 % (ModuleType
, LibraryPath
), File
=self
.MetaFile
,
1672 ExtraData
="consumed by [%s]" % str(Module
))
1674 LibraryInstance
[LibraryClassName
] = LibraryModule
1675 LibraryConsumerList
.append(LibraryModule
)
1676 EdkLogger
.verbose("\t" + str(LibraryClassName
) + " : " + str(LibraryModule
))
1678 LibraryModule
= LibraryInstance
[LibraryClassName
]
1680 if LibraryModule
== None:
1683 if LibraryModule
.ConstructorList
!= [] and LibraryModule
not in Constructor
:
1684 Constructor
.append(LibraryModule
)
1686 if LibraryModule
not in ConsumedByList
:
1687 ConsumedByList
[LibraryModule
] = []
1688 # don't add current module itself to consumer list
1690 if M
in ConsumedByList
[LibraryModule
]:
1692 ConsumedByList
[LibraryModule
].append(M
)
1694 # Initialize the sorted output list to the empty set
1696 SortedLibraryList
= []
1698 # Q <- Set of all nodes with no incoming edges
1700 LibraryList
= [] #LibraryInstance.values()
1702 for LibraryClassName
in LibraryInstance
:
1703 M
= LibraryInstance
[LibraryClassName
]
1704 LibraryList
.append(M
)
1705 if ConsumedByList
[M
] == []:
1709 # start the DAG algorithm
1713 while Q
== [] and EdgeRemoved
:
1715 # for each node Item with a Constructor
1716 for Item
in LibraryList
:
1717 if Item
not in Constructor
:
1719 # for each Node without a constructor with an edge e from Item to Node
1720 for Node
in ConsumedByList
[Item
]:
1721 if Node
in Constructor
:
1723 # remove edge e from the graph if Node has no constructor
1724 ConsumedByList
[Item
].remove(Node
)
1726 if ConsumedByList
[Item
] == []:
1727 # insert Item into Q
1732 # DAG is done if there's no more incoming edge for all nodes
1736 # remove node from Q
1739 SortedLibraryList
.append(Node
)
1741 # for each node Item with an edge e from Node to Item do
1742 for Item
in LibraryList
:
1743 if Node
not in ConsumedByList
[Item
]:
1745 # remove edge e from the graph
1746 ConsumedByList
[Item
].remove(Node
)
1748 if ConsumedByList
[Item
] != []:
1750 # insert Item into Q, if Item has no other incoming edges
1754 # if any remaining node Item in the graph has a constructor and an incoming edge, then the graph has a cycle
1756 for Item
in LibraryList
:
1757 if ConsumedByList
[Item
] != [] and Item
in Constructor
and len(Constructor
) > 1:
1758 ErrorMessage
= "\tconsumed by " + "\n\tconsumed by ".join([str(L
) for L
in ConsumedByList
[Item
]])
1759 EdkLogger
.error("build", BUILD_ERROR
, 'Library [%s] with constructors has a cycle' % str(Item
),
1760 ExtraData
=ErrorMessage
, File
=self
.MetaFile
)
1761 if Item
not in SortedLibraryList
:
1762 SortedLibraryList
.append(Item
)
1765 # Build the list of constructor and destructir names
1766 # The DAG Topo sort produces the destructor order, so the list of constructors must generated in the reverse order
1768 SortedLibraryList
.reverse()
1769 return SortedLibraryList
1772 ## Override PCD setting (type, value, ...)
1774 # @param ToPcd The PCD to be overrided
1775 # @param FromPcd The PCD overrideing from
1777 def _OverridePcd(self
, ToPcd
, FromPcd
, Module
=""):
1779 # in case there's PCDs coming from FDF file, which have no type given.
1780 # at this point, ToPcd.Type has the type found from dependent
1784 if ToPcd
.Pending
and FromPcd
.Type
not in [None, '']:
1785 ToPcd
.Type
= FromPcd
.Type
1786 elif (ToPcd
.Type
not in [None, '']) and (FromPcd
.Type
not in [None, ''])\
1787 and (ToPcd
.Type
!= FromPcd
.Type
) and (ToPcd
.Type
in FromPcd
.Type
):
1788 if ToPcd
.Type
.strip() == "DynamicEx":
1789 ToPcd
.Type
= FromPcd
.Type
1790 elif ToPcd
.Type
not in [None, ''] and FromPcd
.Type
not in [None, ''] \
1791 and ToPcd
.Type
!= FromPcd
.Type
:
1792 EdkLogger
.error("build", OPTION_CONFLICT
, "Mismatched PCD type",
1793 ExtraData
="%s.%s is defined as [%s] in module %s, but as [%s] in platform."\
1794 % (ToPcd
.TokenSpaceGuidCName
, ToPcd
.TokenCName
,
1795 ToPcd
.Type
, Module
, FromPcd
.Type
),
1798 if FromPcd
.MaxDatumSize
not in [None, '']:
1799 ToPcd
.MaxDatumSize
= FromPcd
.MaxDatumSize
1800 if FromPcd
.DefaultValue
not in [None, '']:
1801 ToPcd
.DefaultValue
= FromPcd
.DefaultValue
1802 if FromPcd
.TokenValue
not in [None, '']:
1803 ToPcd
.TokenValue
= FromPcd
.TokenValue
1804 if FromPcd
.MaxDatumSize
not in [None, '']:
1805 ToPcd
.MaxDatumSize
= FromPcd
.MaxDatumSize
1806 if FromPcd
.DatumType
not in [None, '']:
1807 ToPcd
.DatumType
= FromPcd
.DatumType
1808 if FromPcd
.SkuInfoList
not in [None, '', []]:
1809 ToPcd
.SkuInfoList
= FromPcd
.SkuInfoList
1811 # check the validation of datum
1812 IsValid
, Cause
= CheckPcdDatum(ToPcd
.DatumType
, ToPcd
.DefaultValue
)
1814 EdkLogger
.error('build', FORMAT_INVALID
, Cause
, File
=self
.MetaFile
,
1815 ExtraData
="%s.%s" % (ToPcd
.TokenSpaceGuidCName
, ToPcd
.TokenCName
))
1816 ToPcd
.validateranges
= FromPcd
.validateranges
1817 ToPcd
.validlists
= FromPcd
.validlists
1818 ToPcd
.expressions
= FromPcd
.expressions
1820 if ToPcd
.DatumType
== "VOID*" and ToPcd
.MaxDatumSize
in ['', None]:
1821 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "No MaxDatumSize specified for PCD %s.%s" \
1822 % (ToPcd
.TokenSpaceGuidCName
, ToPcd
.TokenCName
))
1823 Value
= ToPcd
.DefaultValue
1824 if Value
in [None, '']:
1825 ToPcd
.MaxDatumSize
= '1'
1826 elif Value
[0] == 'L':
1827 ToPcd
.MaxDatumSize
= str((len(Value
) - 2) * 2)
1828 elif Value
[0] == '{':
1829 ToPcd
.MaxDatumSize
= str(len(Value
.split(',')))
1831 ToPcd
.MaxDatumSize
= str(len(Value
) - 1)
1833 # apply default SKU for dynamic PCDS if specified one is not available
1834 if (ToPcd
.Type
in PCD_DYNAMIC_TYPE_LIST
or ToPcd
.Type
in PCD_DYNAMIC_EX_TYPE_LIST
) \
1835 and ToPcd
.SkuInfoList
in [None, {}, '']:
1836 if self
.Platform
.SkuName
in self
.Platform
.SkuIds
:
1837 SkuName
= self
.Platform
.SkuName
1840 ToPcd
.SkuInfoList
= {
1841 SkuName
: SkuInfoClass(SkuName
, self
.Platform
.SkuIds
[SkuName
], '', '', '', '', '', ToPcd
.DefaultValue
)
1844 ## Apply PCD setting defined platform to a module
1846 # @param Module The module from which the PCD setting will be overrided
1848 # @retval PCD_list The list PCDs with settings from platform
1850 def ApplyPcdSetting(self
, Module
, Pcds
):
1851 # for each PCD in module
1852 for Name
,Guid
in Pcds
:
1853 PcdInModule
= Pcds
[Name
,Guid
]
1854 # find out the PCD setting in platform
1855 if (Name
,Guid
) in self
.Platform
.Pcds
:
1856 PcdInPlatform
= self
.Platform
.Pcds
[Name
,Guid
]
1858 PcdInPlatform
= None
1859 # then override the settings if any
1860 self
._OverridePcd
(PcdInModule
, PcdInPlatform
, Module
)
1861 # resolve the VariableGuid value
1862 for SkuId
in PcdInModule
.SkuInfoList
:
1863 Sku
= PcdInModule
.SkuInfoList
[SkuId
]
1864 if Sku
.VariableGuid
== '': continue
1865 Sku
.VariableGuidValue
= GuidValue(Sku
.VariableGuid
, self
.PackageList
)
1866 if Sku
.VariableGuidValue
== None:
1867 PackageList
= "\n\t".join([str(P
) for P
in self
.PackageList
])
1870 RESOURCE_NOT_AVAILABLE
,
1871 "Value of GUID [%s] is not found in" % Sku
.VariableGuid
,
1872 ExtraData
=PackageList
+ "\n\t(used with %s.%s from module %s)" \
1873 % (Guid
, Name
, str(Module
)),
1877 # override PCD settings with module specific setting
1878 if Module
in self
.Platform
.Modules
:
1879 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
1880 for Key
in PlatformModule
.Pcds
:
1882 self
._OverridePcd
(Pcds
[Key
], PlatformModule
.Pcds
[Key
], Module
)
1883 return Pcds
.values()
1885 ## Resolve library names to library modules
1887 # (for Edk.x modules)
1889 # @param Module The module from which the library names will be resolved
1891 # @retval library_list The list of library modules
1893 def ResolveLibraryReference(self
, Module
):
1894 EdkLogger
.verbose("")
1895 EdkLogger
.verbose("Library instances of module [%s] [%s]:" % (str(Module
), self
.Arch
))
1896 LibraryConsumerList
= [Module
]
1898 # "CompilerStub" is a must for Edk modules
1899 if Module
.Libraries
:
1900 Module
.Libraries
.append("CompilerStub")
1902 while len(LibraryConsumerList
) > 0:
1903 M
= LibraryConsumerList
.pop()
1904 for LibraryName
in M
.Libraries
:
1905 Library
= self
.Platform
.LibraryClasses
[LibraryName
, ':dummy:']
1907 for Key
in self
.Platform
.LibraryClasses
.data
.keys():
1908 if LibraryName
.upper() == Key
.upper():
1909 Library
= self
.Platform
.LibraryClasses
[Key
, ':dummy:']
1912 EdkLogger
.warn("build", "Library [%s] is not found" % LibraryName
, File
=str(M
),
1913 ExtraData
="\t%s [%s]" % (str(Module
), self
.Arch
))
1916 if Library
not in LibraryList
:
1917 LibraryList
.append(Library
)
1918 LibraryConsumerList
.append(Library
)
1919 EdkLogger
.verbose("\t" + LibraryName
+ " : " + str(Library
) + ' ' + str(type(Library
)))
1922 ## Calculate the priority value of the build option
1924 # @param Key Build option definition contain: TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
1926 # @retval Value Priority value based on the priority list.
1928 def CalculatePriorityValue(self
, Key
):
1929 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
.split('_')
1930 PriorityValue
= 0x11111
1932 PriorityValue
&= 0x01111
1933 if ToolChain
== "*":
1934 PriorityValue
&= 0x10111
1936 PriorityValue
&= 0x11011
1937 if CommandType
== "*":
1938 PriorityValue
&= 0x11101
1940 PriorityValue
&= 0x11110
1942 return self
.PrioList
["0x%0.5x"%PriorityValue
]
1945 ## Expand * in build option key
1947 # @param Options Options to be expanded
1949 # @retval options Options expanded
1951 def _ExpandBuildOption(self
, Options
, ModuleStyle
=None):
1958 # Construct a list contain the build options which need override.
1962 # Key[0] -- tool family
1963 # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
1965 if Key
[0] == self
.BuildRuleFamily
:
1966 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
[1].split('_')
1967 if Target
== self
.BuildTarget
or Target
== "*":
1968 if ToolChain
== self
.ToolChain
or ToolChain
== "*":
1969 if Arch
== self
.Arch
or Arch
== "*":
1970 if Options
[Key
].startswith("="):
1971 if OverrideList
.get(Key
[1]) != None:
1972 OverrideList
.pop(Key
[1])
1973 OverrideList
[Key
[1]] = Options
[Key
]
1976 # Use the highest priority value.
1978 if (len(OverrideList
) >= 2):
1979 KeyList
= OverrideList
.keys()
1980 for Index
in range(len(KeyList
)):
1981 NowKey
= KeyList
[Index
]
1982 Target1
, ToolChain1
, Arch1
, CommandType1
, Attr1
= NowKey
.split("_")
1983 for Index1
in range(len(KeyList
) - Index
- 1):
1984 NextKey
= KeyList
[Index1
+ Index
+ 1]
1986 # Compare two Key, if one is included by another, choose the higher priority one
1988 Target2
, ToolChain2
, Arch2
, CommandType2
, Attr2
= NextKey
.split("_")
1989 if Target1
== Target2
or Target1
== "*" or Target2
== "*":
1990 if ToolChain1
== ToolChain2
or ToolChain1
== "*" or ToolChain2
== "*":
1991 if Arch1
== Arch2
or Arch1
== "*" or Arch2
== "*":
1992 if CommandType1
== CommandType2
or CommandType1
== "*" or CommandType2
== "*":
1993 if Attr1
== Attr2
or Attr1
== "*" or Attr2
== "*":
1994 if self
.CalculatePriorityValue(NowKey
) > self
.CalculatePriorityValue(NextKey
):
1995 if Options
.get((self
.BuildRuleFamily
, NextKey
)) != None:
1996 Options
.pop((self
.BuildRuleFamily
, NextKey
))
1998 if Options
.get((self
.BuildRuleFamily
, NowKey
)) != None:
1999 Options
.pop((self
.BuildRuleFamily
, NowKey
))
2003 if ModuleStyle
!= None and len (Key
) > 2:
2004 # Check Module style is EDK or EDKII.
2005 # Only append build option for the matched style module.
2006 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
2008 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
2011 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
2012 # if tool chain family doesn't match, skip it
2013 if Tool
in self
.ToolDefinition
and Family
!= "":
2014 FamilyIsNull
= False
2015 if self
.ToolDefinition
[Tool
].get(TAB_TOD_DEFINES_BUILDRULEFAMILY
, "") != "":
2016 if Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_BUILDRULEFAMILY
]:
2018 elif Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
2021 # expand any wildcard
2022 if Target
== "*" or Target
== self
.BuildTarget
:
2023 if Tag
== "*" or Tag
== self
.ToolChain
:
2024 if Arch
== "*" or Arch
== self
.Arch
:
2025 if Tool
not in BuildOptions
:
2026 BuildOptions
[Tool
] = {}
2027 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
]:
2028 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2030 # append options for the same tool
2031 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
2032 # Build Option Family has been checked, which need't to be checked again for family.
2033 if FamilyMatch
or FamilyIsNull
:
2037 if ModuleStyle
!= None and len (Key
) > 2:
2038 # Check Module style is EDK or EDKII.
2039 # Only append build option for the matched style module.
2040 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
2042 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
2045 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
2046 # if tool chain family doesn't match, skip it
2047 if Tool
not in self
.ToolDefinition
or Family
=="":
2049 # option has been added before
2050 if Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
2053 # expand any wildcard
2054 if Target
== "*" or Target
== self
.BuildTarget
:
2055 if Tag
== "*" or Tag
== self
.ToolChain
:
2056 if Arch
== "*" or Arch
== self
.Arch
:
2057 if Tool
not in BuildOptions
:
2058 BuildOptions
[Tool
] = {}
2059 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
]:
2060 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2062 # append options for the same tool
2063 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
2066 ## Append build options in platform to a module
2068 # @param Module The module to which the build options will be appened
2070 # @retval options The options appended with build options in platform
2072 def ApplyBuildOption(self
, Module
):
2073 # Get the different options for the different style module
2074 if Module
.AutoGenVersion
< 0x00010005:
2075 PlatformOptions
= self
.EdkBuildOption
2077 PlatformOptions
= self
.EdkIIBuildOption
2078 ModuleOptions
= self
._ExpandBuildOption
(Module
.BuildOptions
)
2079 if Module
in self
.Platform
.Modules
:
2080 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
2081 PlatformModuleOptions
= self
._ExpandBuildOption
(PlatformModule
.BuildOptions
)
2083 PlatformModuleOptions
= {}
2085 BuildRuleOrder
= None
2086 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, PlatformModuleOptions
]:
2087 for Tool
in Options
:
2088 for Attr
in Options
[Tool
]:
2089 if Attr
== TAB_TOD_DEFINES_BUILDRULEORDER
:
2090 BuildRuleOrder
= Options
[Tool
][Attr
]
2092 AllTools
= set(ModuleOptions
.keys() + PlatformOptions
.keys() + PlatformModuleOptions
.keys() + self
.ToolDefinition
.keys())
2094 for Tool
in AllTools
:
2095 if Tool
not in BuildOptions
:
2096 BuildOptions
[Tool
] = {}
2098 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, PlatformModuleOptions
]:
2099 if Tool
not in Options
:
2101 for Attr
in Options
[Tool
]:
2102 Value
= Options
[Tool
][Attr
]
2104 # Do not generate it in Makefile
2106 if Attr
== TAB_TOD_DEFINES_BUILDRULEORDER
:
2108 if Attr
not in BuildOptions
[Tool
]:
2109 BuildOptions
[Tool
][Attr
] = ""
2110 # check if override is indicated
2111 if Value
.startswith('='):
2112 BuildOptions
[Tool
][Attr
] = Value
[1:]
2114 BuildOptions
[Tool
][Attr
] += " " + Value
2115 if Module
.AutoGenVersion
< 0x00010005 and self
.Workspace
.UniFlag
!= None:
2117 # Override UNI flag only for EDK module.
2119 if 'BUILD' not in BuildOptions
:
2120 BuildOptions
['BUILD'] = {}
2121 BuildOptions
['BUILD']['FLAGS'] = self
.Workspace
.UniFlag
2122 return BuildOptions
, BuildRuleOrder
2124 Platform
= property(_GetPlatform
)
2125 Name
= property(_GetName
)
2126 Guid
= property(_GetGuid
)
2127 Version
= property(_GetVersion
)
2129 OutputDir
= property(_GetOutputDir
)
2130 BuildDir
= property(_GetBuildDir
)
2131 MakeFileDir
= property(_GetMakeFileDir
)
2132 FdfFile
= property(_GetFdfFile
)
2134 PcdTokenNumber
= property(_GetPcdTokenNumbers
) # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
2135 DynamicPcdList
= property(_GetDynamicPcdList
) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
2136 NonDynamicPcdList
= property(_GetNonDynamicPcdList
) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
2137 NonDynamicPcdDict
= property(_GetNonDynamicPcdDict
)
2138 PackageList
= property(_GetPackageList
)
2140 ToolDefinition
= property(_GetToolDefinition
) # toolcode : tool path
2141 ToolDefinitionFile
= property(_GetToolDefFile
) # toolcode : lib path
2142 ToolChainFamily
= property(_GetToolChainFamily
)
2143 BuildRuleFamily
= property(_GetBuildRuleFamily
)
2144 BuildOption
= property(_GetBuildOptions
) # toolcode : option
2145 EdkBuildOption
= property(_GetEdkBuildOptions
) # edktoolcode : option
2146 EdkIIBuildOption
= property(_GetEdkIIBuildOptions
) # edkiitoolcode : option
2148 BuildCommand
= property(_GetBuildCommand
)
2149 BuildRule
= property(_GetBuildRule
)
2150 ModuleAutoGenList
= property(_GetModuleAutoGenList
)
2151 LibraryAutoGenList
= property(_GetLibraryAutoGenList
)
2152 GenFdsCommand
= property(_GenFdsCommand
)
2154 ## ModuleAutoGen class
2156 # This class encapsules the AutoGen behaviors for the build tools. In addition to
2157 # the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according
2158 # to the [depex] section in module's inf file.
2160 class ModuleAutoGen(AutoGen
):
2161 ## The real constructor of ModuleAutoGen
2163 # This method is not supposed to be called by users of ModuleAutoGen. It's
2164 # only used by factory method __new__() to do real initialization work for an
2165 # object of ModuleAutoGen
2167 # @param Workspace EdkIIWorkspaceBuild object
2168 # @param ModuleFile The path of module file
2169 # @param Target Build target (DEBUG, RELEASE)
2170 # @param Toolchain Name of tool chain
2171 # @param Arch The arch the module supports
2172 # @param PlatformFile Platform meta-file
2174 def _Init(self
, Workspace
, ModuleFile
, Target
, Toolchain
, Arch
, PlatformFile
):
2175 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen module [%s] [%s]" % (ModuleFile
, Arch
))
2176 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (ModuleFile
, Arch
, Toolchain
, Target
)
2178 self
.Workspace
= Workspace
2179 self
.WorkspaceDir
= Workspace
.WorkspaceDir
2181 self
.MetaFile
= ModuleFile
2182 self
.PlatformInfo
= PlatformAutoGen(Workspace
, PlatformFile
, Target
, Toolchain
, Arch
)
2183 # check if this module is employed by active platform
2184 if not self
.PlatformInfo
.ValidModule(self
.MetaFile
):
2185 EdkLogger
.verbose("Module [%s] for [%s] is not employed by active platform\n" \
2186 % (self
.MetaFile
, Arch
))
2189 self
.SourceDir
= self
.MetaFile
.SubDir
2190 if self
.SourceDir
.upper().find(self
.WorkspaceDir
.upper()) == 0:
2191 self
.SourceDir
= self
.SourceDir
[len(self
.WorkspaceDir
) + 1:]
2193 self
.SourceOverrideDir
= None
2194 # use overrided path defined in DSC file
2195 if self
.MetaFile
.Key
in GlobalData
.gOverrideDir
:
2196 self
.SourceOverrideDir
= GlobalData
.gOverrideDir
[self
.MetaFile
.Key
]
2198 self
.ToolChain
= Toolchain
2199 self
.BuildTarget
= Target
2201 self
.ToolChainFamily
= self
.PlatformInfo
.ToolChainFamily
2202 self
.BuildRuleFamily
= self
.PlatformInfo
.BuildRuleFamily
2204 self
.IsMakeFileCreated
= False
2205 self
.IsCodeFileCreated
= False
2206 self
.IsAsBuiltInfCreated
= False
2207 self
.DepexGenerated
= False
2209 self
.BuildDatabase
= self
.Workspace
.BuildDatabase
2210 self
.BuildRuleOrder
= None
2215 self
._Version
= None
2216 self
._ModuleType
= None
2217 self
._ComponentType
= None
2218 self
._PcdIsDriver
= None
2219 self
._AutoGenVersion
= None
2220 self
._LibraryFlag
= None
2221 self
._CustomMakefile
= None
2224 self
._BuildDir
= None
2225 self
._OutputDir
= None
2226 self
._DebugDir
= None
2227 self
._MakeFileDir
= None
2229 self
._IncludePathList
= None
2230 self
._AutoGenFileList
= None
2231 self
._UnicodeFileList
= None
2232 self
._SourceFileList
= None
2233 self
._ObjectFileList
= None
2234 self
._BinaryFileList
= None
2236 self
._DependentPackageList
= None
2237 self
._DependentLibraryList
= None
2238 self
._LibraryAutoGenList
= None
2239 self
._DerivedPackageList
= None
2240 self
._ModulePcdList
= None
2241 self
._LibraryPcdList
= None
2242 self
._PcdComments
= sdict()
2243 self
._GuidList
= None
2244 self
._GuidsUsedByPcd
= None
2245 self
._GuidComments
= sdict()
2246 self
._ProtocolList
= None
2247 self
._ProtocolComments
= sdict()
2248 self
._PpiList
= None
2249 self
._PpiComments
= sdict()
2250 self
._DepexList
= None
2251 self
._DepexExpressionList
= None
2252 self
._BuildOption
= None
2253 self
._BuildOptionIncPathList
= None
2254 self
._BuildTargets
= None
2255 self
._IntroBuildTargetList
= None
2256 self
._FinalBuildTargetList
= None
2257 self
._FileTypes
= None
2258 self
._BuildRules
= None
2260 ## The Modules referenced to this Library
2261 # Only Library has this attribute
2262 self
._ReferenceModules
= []
2264 ## Store the FixedAtBuild Pcds
2266 self
._FixedAtBuildPcds
= []
2271 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
2273 # Get FixedAtBuild Pcds of this Module
2274 def _GetFixedAtBuildPcds(self
):
2275 if self
._FixedAtBuildPcds
:
2276 return self
._FixedAtBuildPcds
2277 for Pcd
in self
.ModulePcdList
:
2279 if not (Pcd
.Pending
== False and Pcd
.Type
== "FixedAtBuild"):
2281 elif Pcd
.Type
!= "FixedAtBuild":
2283 if Pcd
not in self
._FixedAtBuildPcds
:
2284 self
._FixedAtBuildPcds
.append(Pcd
)
2286 return self
._FixedAtBuildPcds
2288 # Macros could be used in build_rule.txt (also Makefile)
2289 def _GetMacros(self
):
2290 if self
._Macro
== None:
2291 self
._Macro
= sdict()
2292 self
._Macro
["WORKSPACE" ] = self
.WorkspaceDir
2293 self
._Macro
["MODULE_NAME" ] = self
.Name
2294 self
._Macro
["MODULE_GUID" ] = self
.Guid
2295 self
._Macro
["MODULE_VERSION" ] = self
.Version
2296 self
._Macro
["MODULE_TYPE" ] = self
.ModuleType
2297 self
._Macro
["MODULE_FILE" ] = str(self
.MetaFile
)
2298 self
._Macro
["MODULE_FILE_BASE_NAME" ] = self
.MetaFile
.BaseName
2299 self
._Macro
["MODULE_RELATIVE_DIR" ] = self
.SourceDir
2300 self
._Macro
["MODULE_DIR" ] = self
.SourceDir
2302 self
._Macro
["BASE_NAME" ] = self
.Name
2304 self
._Macro
["ARCH" ] = self
.Arch
2305 self
._Macro
["TOOLCHAIN" ] = self
.ToolChain
2306 self
._Macro
["TOOLCHAIN_TAG" ] = self
.ToolChain
2307 self
._Macro
["TOOL_CHAIN_TAG" ] = self
.ToolChain
2308 self
._Macro
["TARGET" ] = self
.BuildTarget
2310 self
._Macro
["BUILD_DIR" ] = self
.PlatformInfo
.BuildDir
2311 self
._Macro
["BIN_DIR" ] = os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)
2312 self
._Macro
["LIB_DIR" ] = os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)
2313 self
._Macro
["MODULE_BUILD_DIR" ] = self
.BuildDir
2314 self
._Macro
["OUTPUT_DIR" ] = self
.OutputDir
2315 self
._Macro
["DEBUG_DIR" ] = self
.DebugDir
2318 ## Return the module build data object
2319 def _GetModule(self
):
2320 if self
._Module
== None:
2321 self
._Module
= self
.Workspace
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
2324 ## Return the module name
2325 def _GetBaseName(self
):
2326 return self
.Module
.BaseName
2328 ## Return the module DxsFile if exist
2329 def _GetDxsFile(self
):
2330 return self
.Module
.DxsFile
2332 ## Return the module SourceOverridePath
2333 def _GetSourceOverridePath(self
):
2334 return self
.Module
.SourceOverridePath
2336 ## Return the module meta-file GUID
2339 # To build same module more than once, the module path with FILE_GUID overridden has
2340 # the file name FILE_GUIDmodule.inf, but the relative path (self.MetaFile.File) is the realy path
2341 # in DSC. The overridden GUID can be retrieved from file name
2343 if os
.path
.basename(self
.MetaFile
.File
) != os
.path
.basename(self
.MetaFile
.Path
):
2345 # Length of GUID is 36
2347 return os
.path
.basename(self
.MetaFile
.Path
)[:36]
2348 return self
.Module
.Guid
2350 ## Return the module version
2351 def _GetVersion(self
):
2352 return self
.Module
.Version
2354 ## Return the module type
2355 def _GetModuleType(self
):
2356 return self
.Module
.ModuleType
2358 ## Return the component type (for Edk.x style of module)
2359 def _GetComponentType(self
):
2360 return self
.Module
.ComponentType
2362 ## Return the build type
2363 def _GetBuildType(self
):
2364 return self
.Module
.BuildType
2366 ## Return the PCD_IS_DRIVER setting
2367 def _GetPcdIsDriver(self
):
2368 return self
.Module
.PcdIsDriver
2370 ## Return the autogen version, i.e. module meta-file version
2371 def _GetAutoGenVersion(self
):
2372 return self
.Module
.AutoGenVersion
2374 ## Check if the module is library or not
2375 def _IsLibrary(self
):
2376 if self
._LibraryFlag
== None:
2377 if self
.Module
.LibraryClass
!= None and self
.Module
.LibraryClass
!= []:
2378 self
._LibraryFlag
= True
2380 self
._LibraryFlag
= False
2381 return self
._LibraryFlag
2383 ## Check if the module is binary module or not
2384 def _IsBinaryModule(self
):
2385 return self
.Module
.IsBinaryModule
2387 ## Return the directory to store intermediate files of the module
2388 def _GetBuildDir(self
):
2389 if self
._BuildDir
== None:
2390 self
._BuildDir
= path
.join(
2391 self
.PlatformInfo
.BuildDir
,
2394 self
.MetaFile
.BaseName
2396 CreateDirectory(self
._BuildDir
)
2397 return self
._BuildDir
2399 ## Return the directory to store the intermediate object files of the mdoule
2400 def _GetOutputDir(self
):
2401 if self
._OutputDir
== None:
2402 self
._OutputDir
= path
.join(self
.BuildDir
, "OUTPUT")
2403 CreateDirectory(self
._OutputDir
)
2404 return self
._OutputDir
2406 ## Return the directory to store auto-gened source files of the mdoule
2407 def _GetDebugDir(self
):
2408 if self
._DebugDir
== None:
2409 self
._DebugDir
= path
.join(self
.BuildDir
, "DEBUG")
2410 CreateDirectory(self
._DebugDir
)
2411 return self
._DebugDir
2413 ## Return the path of custom file
2414 def _GetCustomMakefile(self
):
2415 if self
._CustomMakefile
== None:
2416 self
._CustomMakefile
= {}
2417 for Type
in self
.Module
.CustomMakefile
:
2418 if Type
in gMakeTypeMap
:
2419 MakeType
= gMakeTypeMap
[Type
]
2422 if self
.SourceOverrideDir
!= None:
2423 File
= os
.path
.join(self
.SourceOverrideDir
, self
.Module
.CustomMakefile
[Type
])
2424 if not os
.path
.exists(File
):
2425 File
= os
.path
.join(self
.SourceDir
, self
.Module
.CustomMakefile
[Type
])
2427 File
= os
.path
.join(self
.SourceDir
, self
.Module
.CustomMakefile
[Type
])
2428 self
._CustomMakefile
[MakeType
] = File
2429 return self
._CustomMakefile
2431 ## Return the directory of the makefile
2433 # @retval string The directory string of module's makefile
2435 def _GetMakeFileDir(self
):
2436 return self
.BuildDir
2438 ## Return build command string
2440 # @retval string Build command string
2442 def _GetBuildCommand(self
):
2443 return self
.PlatformInfo
.BuildCommand
2445 ## Get object list of all packages the module and its dependent libraries belong to
2447 # @retval list The list of package object
2449 def _GetDerivedPackageList(self
):
2451 for M
in [self
.Module
] + self
.DependentLibraryList
:
2452 for Package
in M
.Packages
:
2453 if Package
in PackageList
:
2455 PackageList
.append(Package
)
2458 ## Get the depex string
2460 # @return : a string contain all depex expresion.
2461 def _GetDepexExpresionString(self
):
2464 ## DPX_SOURCE IN Define section.
2465 if self
.Module
.DxsFile
:
2467 for M
in [self
.Module
] + self
.DependentLibraryList
:
2468 Filename
= M
.MetaFile
.Path
2469 InfObj
= InfSectionParser
.InfSectionParser(Filename
)
2470 DepexExpresionList
= InfObj
.GetDepexExpresionList()
2471 for DepexExpresion
in DepexExpresionList
:
2472 for key
in DepexExpresion
.keys():
2473 Arch
, ModuleType
= key
2474 # the type of build module is USER_DEFINED.
2475 # All different DEPEX section tags would be copied into the As Built INF file
2476 # and there would be separate DEPEX section tags
2477 if self
.ModuleType
.upper() == SUP_MODULE_USER_DEFINED
:
2478 if (Arch
.upper() == self
.Arch
.upper()) and (ModuleType
.upper() != TAB_ARCH_COMMON
):
2479 DepexList
.append({(Arch
, ModuleType
): DepexExpresion
[key
][:]})
2481 if Arch
.upper() == TAB_ARCH_COMMON
or \
2482 (Arch
.upper() == self
.Arch
.upper() and \
2483 ModuleType
.upper() in [TAB_ARCH_COMMON
, self
.ModuleType
.upper()]):
2484 DepexList
.append({(Arch
, ModuleType
): DepexExpresion
[key
][:]})
2486 #the type of build module is USER_DEFINED.
2487 if self
.ModuleType
.upper() == SUP_MODULE_USER_DEFINED
:
2488 for Depex
in DepexList
:
2489 for key
in Depex
.keys():
2490 DepexStr
+= '[Depex.%s.%s]\n' % key
2491 DepexStr
+= '\n'.join(['# '+ val
for val
in Depex
[key
]])
2494 return '[Depex.%s]\n' % self
.Arch
2497 #the type of build module not is USER_DEFINED.
2499 for Depex
in DepexList
:
2504 for D
in Depex
.values():
2505 DepexStr
+= ' '.join([val
for val
in D
])
2506 Index
= DepexStr
.find('END')
2507 if Index
> -1 and Index
== len(DepexStr
) - 3:
2508 DepexStr
= DepexStr
[:-3]
2509 DepexStr
= DepexStr
.strip()
2512 DepexStr
= DepexStr
.lstrip('(').rstrip(')').strip()
2514 return '[Depex.%s]\n' % self
.Arch
2515 return '[Depex.%s]\n# ' % self
.Arch
+ DepexStr
2517 ## Merge dependency expression
2519 # @retval list The token list of the dependency expression after parsed
2521 def _GetDepexTokenList(self
):
2522 if self
._DepexList
== None:
2523 self
._DepexList
= {}
2524 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
2525 return self
._DepexList
2527 self
._DepexList
[self
.ModuleType
] = []
2529 for ModuleType
in self
._DepexList
:
2530 DepexList
= self
._DepexList
[ModuleType
]
2532 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
2534 for M
in [self
.Module
] + self
.DependentLibraryList
:
2536 for D
in M
.Depex
[self
.Arch
, ModuleType
]:
2538 DepexList
.append('AND')
2539 DepexList
.append('(')
2541 if DepexList
[-1] == 'END': # no need of a END at this time
2543 DepexList
.append(')')
2546 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexList
))
2547 if 'BEFORE' in DepexList
or 'AFTER' in DepexList
:
2549 if len(DepexList
) > 0:
2550 EdkLogger
.verbose('')
2551 return self
._DepexList
2553 ## Merge dependency expression
2555 # @retval list The token list of the dependency expression after parsed
2557 def _GetDepexExpressionTokenList(self
):
2558 if self
._DepexExpressionList
== None:
2559 self
._DepexExpressionList
= {}
2560 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
2561 return self
._DepexExpressionList
2563 self
._DepexExpressionList
[self
.ModuleType
] = ''
2565 for ModuleType
in self
._DepexExpressionList
:
2566 DepexExpressionList
= self
._DepexExpressionList
[ModuleType
]
2568 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
2570 for M
in [self
.Module
] + self
.DependentLibraryList
:
2572 for D
in M
.DepexExpression
[self
.Arch
, ModuleType
]:
2573 if DepexExpressionList
!= '':
2574 DepexExpressionList
+= ' AND '
2575 DepexExpressionList
+= '('
2576 DepexExpressionList
+= D
2577 DepexExpressionList
= DepexExpressionList
.rstrip('END').strip()
2578 DepexExpressionList
+= ')'
2581 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexExpressionList
))
2582 if 'BEFORE' in DepexExpressionList
or 'AFTER' in DepexExpressionList
:
2584 if len(DepexExpressionList
) > 0:
2585 EdkLogger
.verbose('')
2586 self
._DepexExpressionList
[ModuleType
] = DepexExpressionList
2587 return self
._DepexExpressionList
2589 ## Return the list of specification version required for the module
2591 # @retval list The list of specification defined in module file
2593 def _GetSpecification(self
):
2594 return self
.Module
.Specification
2596 ## Tool option for the module build
2598 # @param PlatformInfo The object of PlatformBuildInfo
2599 # @retval dict The dict containing valid options
2601 def _GetModuleBuildOption(self
):
2602 if self
._BuildOption
== None:
2603 self
._BuildOption
, self
.BuildRuleOrder
= self
.PlatformInfo
.ApplyBuildOption(self
.Module
)
2604 if self
.BuildRuleOrder
:
2605 self
.BuildRuleOrder
= ['.%s' % Ext
for Ext
in self
.BuildRuleOrder
.split()]
2606 return self
._BuildOption
2608 ## Get include path list from tool option for the module build
2610 # @retval list The include path list
2612 def _GetBuildOptionIncPathList(self
):
2613 if self
._BuildOptionIncPathList
== None:
2615 # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
2616 # is the former use /I , the Latter used -I to specify include directories
2618 if self
.PlatformInfo
.ToolChainFamily
in ('MSFT'):
2619 gBuildOptIncludePattern
= re
.compile(r
"(?:.*?)/I[ \t]*([^ ]*)", re
.MULTILINE|re
.DOTALL
)
2620 elif self
.PlatformInfo
.ToolChainFamily
in ('INTEL', 'GCC', 'RVCT'):
2621 gBuildOptIncludePattern
= re
.compile(r
"(?:.*?)-I[ \t]*([^ ]*)", re
.MULTILINE|re
.DOTALL
)
2624 # New ToolChainFamily, don't known whether there is option to specify include directories
2626 self
._BuildOptionIncPathList
= []
2627 return self
._BuildOptionIncPathList
2629 BuildOptionIncPathList
= []
2630 for Tool
in ('CC', 'PP', 'VFRPP', 'ASLPP', 'ASLCC', 'APP', 'ASM'):
2633 FlagOption
= self
.BuildOption
[Tool
][Attr
]
2637 if self
.PlatformInfo
.ToolChainFamily
!= 'RVCT':
2638 IncPathList
= [NormPath(Path
, self
.Macros
) for Path
in gBuildOptIncludePattern
.findall(FlagOption
)]
2641 # RVCT may specify a list of directory seperated by commas
2644 for Path
in gBuildOptIncludePattern
.findall(FlagOption
):
2645 PathList
= GetSplitList(Path
, TAB_COMMA_SPLIT
)
2646 IncPathList
+= [NormPath(PathEntry
, self
.Macros
) for PathEntry
in PathList
]
2649 # EDK II modules must not reference header files outside of the packages they depend on or
2650 # within the module's directory tree. Report error if violation.
2652 if self
.AutoGenVersion
>= 0x00010005 and len(IncPathList
) > 0:
2653 for Path
in IncPathList
:
2654 if (Path
not in self
.IncludePathList
) and (CommonPath([Path
, self
.MetaFile
.Dir
]) != self
.MetaFile
.Dir
):
2655 ErrMsg
= "The include directory for the EDK II module in this line is invalid %s specified in %s FLAGS '%s'" % (Path
, Tool
, FlagOption
)
2656 EdkLogger
.error("build",
2659 File
= str(self
.MetaFile
))
2662 BuildOptionIncPathList
+= IncPathList
2664 self
._BuildOptionIncPathList
= BuildOptionIncPathList
2666 return self
._BuildOptionIncPathList
2668 ## Return a list of files which can be built from source
2670 # What kind of files can be built is determined by build rules in
2671 # $(CONF_DIRECTORY)/build_rule.txt and toolchain family.
2673 def _GetSourceFileList(self
):
2674 if self
._SourceFileList
== None:
2675 self
._SourceFileList
= []
2676 for F
in self
.Module
.Sources
:
2678 if F
.TagName
not in ("", "*", self
.ToolChain
):
2679 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "The toolchain [%s] for processing file [%s] is found, "
2680 "but [%s] is needed" % (F
.TagName
, str(F
), self
.ToolChain
))
2682 # match tool chain family
2683 if F
.ToolChainFamily
not in ("", "*", self
.ToolChainFamily
):
2686 "The file [%s] must be built by tools of [%s], " \
2687 "but current toolchain family is [%s]" \
2688 % (str(F
), F
.ToolChainFamily
, self
.ToolChainFamily
))
2691 # add the file path into search path list for file including
2692 if F
.Dir
not in self
.IncludePathList
and self
.AutoGenVersion
>= 0x00010005:
2693 self
.IncludePathList
.insert(0, F
.Dir
)
2694 self
._SourceFileList
.append(F
)
2695 self
._ApplyBuildRule
(F
, TAB_UNKNOWN_FILE
)
2696 return self
._SourceFileList
2698 ## Return the list of unicode files
2699 def _GetUnicodeFileList(self
):
2700 if self
._UnicodeFileList
== None:
2701 if TAB_UNICODE_FILE
in self
.FileTypes
:
2702 self
._UnicodeFileList
= self
.FileTypes
[TAB_UNICODE_FILE
]
2704 self
._UnicodeFileList
= []
2705 return self
._UnicodeFileList
2707 ## Return a list of files which can be built from binary
2709 # "Build" binary files are just to copy them to build directory.
2711 # @retval list The list of files which can be built later
2713 def _GetBinaryFiles(self
):
2714 if self
._BinaryFileList
== None:
2715 self
._BinaryFileList
= []
2716 for F
in self
.Module
.Binaries
:
2717 if F
.Target
not in ['COMMON', '*'] and F
.Target
!= self
.BuildTarget
:
2719 self
._BinaryFileList
.append(F
)
2720 self
._ApplyBuildRule
(F
, F
.Type
)
2721 return self
._BinaryFileList
2723 def _GetBuildRules(self
):
2724 if self
._BuildRules
== None:
2726 BuildRuleDatabase
= self
.PlatformInfo
.BuildRule
2727 for Type
in BuildRuleDatabase
.FileTypeList
:
2728 #first try getting build rule by BuildRuleFamily
2729 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.BuildRuleFamily
]
2731 # build type is always module type, but ...
2732 if self
.ModuleType
!= self
.BuildType
:
2733 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.BuildRuleFamily
]
2734 #second try getting build rule by ToolChainFamily
2736 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.ToolChainFamily
]
2738 # build type is always module type, but ...
2739 if self
.ModuleType
!= self
.BuildType
:
2740 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.ToolChainFamily
]
2743 RuleObject
= RuleObject
.Instantiate(self
.Macros
)
2744 BuildRules
[Type
] = RuleObject
2745 for Ext
in RuleObject
.SourceFileExtList
:
2746 BuildRules
[Ext
] = RuleObject
2747 self
._BuildRules
= BuildRules
2748 return self
._BuildRules
2750 def _ApplyBuildRule(self
, File
, FileType
):
2751 if self
._BuildTargets
== None:
2752 self
._IntroBuildTargetList
= set()
2753 self
._FinalBuildTargetList
= set()
2754 self
._BuildTargets
= {}
2755 self
._FileTypes
= {}
2757 SubDirectory
= os
.path
.join(self
.OutputDir
, File
.SubDir
)
2758 if not os
.path
.exists(SubDirectory
):
2759 CreateDirectory(SubDirectory
)
2765 # Make sure to get build rule order value
2767 self
._GetModuleBuildOption
()
2769 while Index
< len(SourceList
):
2770 Source
= SourceList
[Index
]
2774 CreateDirectory(Source
.Dir
)
2776 if File
.IsBinary
and File
== Source
and self
._BinaryFileList
!= None and File
in self
._BinaryFileList
:
2777 # Skip all files that are not binary libraries
2778 if not self
.IsLibrary
:
2780 RuleObject
= self
.BuildRules
[TAB_DEFAULT_BINARY_FILE
]
2781 elif FileType
in self
.BuildRules
:
2782 RuleObject
= self
.BuildRules
[FileType
]
2783 elif Source
.Ext
in self
.BuildRules
:
2784 RuleObject
= self
.BuildRules
[Source
.Ext
]
2786 # stop at no more rules
2788 self
._FinalBuildTargetList
.add(LastTarget
)
2791 FileType
= RuleObject
.SourceFileType
2792 if FileType
not in self
._FileTypes
:
2793 self
._FileTypes
[FileType
] = set()
2794 self
._FileTypes
[FileType
].add(Source
)
2796 # stop at STATIC_LIBRARY for library
2797 if self
.IsLibrary
and FileType
== TAB_STATIC_LIBRARY
:
2799 self
._FinalBuildTargetList
.add(LastTarget
)
2802 Target
= RuleObject
.Apply(Source
, self
.BuildRuleOrder
)
2805 self
._FinalBuildTargetList
.add(LastTarget
)
2807 elif not Target
.Outputs
:
2808 # Only do build for target with outputs
2809 self
._FinalBuildTargetList
.add(Target
)
2811 if FileType
not in self
._BuildTargets
:
2812 self
._BuildTargets
[FileType
] = set()
2813 self
._BuildTargets
[FileType
].add(Target
)
2815 if not Source
.IsBinary
and Source
== File
:
2816 self
._IntroBuildTargetList
.add(Target
)
2818 # to avoid cyclic rule
2819 if FileType
in RuleChain
:
2822 RuleChain
.append(FileType
)
2823 SourceList
.extend(Target
.Outputs
)
2825 FileType
= TAB_UNKNOWN_FILE
2827 def _GetTargets(self
):
2828 if self
._BuildTargets
== None:
2829 self
._IntroBuildTargetList
= set()
2830 self
._FinalBuildTargetList
= set()
2831 self
._BuildTargets
= {}
2832 self
._FileTypes
= {}
2834 #TRICK: call _GetSourceFileList to apply build rule for source files
2835 if self
.SourceFileList
:
2838 #TRICK: call _GetBinaryFileList to apply build rule for binary files
2839 if self
.BinaryFileList
:
2842 return self
._BuildTargets
2844 def _GetIntroTargetList(self
):
2846 return self
._IntroBuildTargetList
2848 def _GetFinalTargetList(self
):
2850 return self
._FinalBuildTargetList
2852 def _GetFileTypes(self
):
2854 return self
._FileTypes
2856 ## Get the list of package object the module depends on
2858 # @retval list The package object list
2860 def _GetDependentPackageList(self
):
2861 return self
.Module
.Packages
2863 ## Return the list of auto-generated code file
2865 # @retval list The list of auto-generated file
2867 def _GetAutoGenFileList(self
):
2868 UniStringAutoGenC
= True
2869 UniStringBinBuffer
= StringIO()
2870 if self
.BuildType
== 'UEFI_HII':
2871 UniStringAutoGenC
= False
2872 if self
._AutoGenFileList
== None:
2873 self
._AutoGenFileList
= {}
2874 AutoGenC
= TemplateString()
2875 AutoGenH
= TemplateString()
2876 StringH
= TemplateString()
2877 GenC
.CreateCode(self
, AutoGenC
, AutoGenH
, StringH
, UniStringAutoGenC
, UniStringBinBuffer
)
2879 # AutoGen.c is generated if there are library classes in inf, or there are object files
2881 if str(AutoGenC
) != "" and (len(self
.Module
.LibraryClasses
) > 0
2882 or TAB_OBJECT_FILE
in self
.FileTypes
):
2883 AutoFile
= PathClass(gAutoGenCodeFileName
, self
.DebugDir
)
2884 self
._AutoGenFileList
[AutoFile
] = str(AutoGenC
)
2885 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
2886 if str(AutoGenH
) != "":
2887 AutoFile
= PathClass(gAutoGenHeaderFileName
, self
.DebugDir
)
2888 self
._AutoGenFileList
[AutoFile
] = str(AutoGenH
)
2889 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
2890 if str(StringH
) != "":
2891 AutoFile
= PathClass(gAutoGenStringFileName
% {"module_name":self
.Name
}, self
.DebugDir
)
2892 self
._AutoGenFileList
[AutoFile
] = str(StringH
)
2893 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
2894 if UniStringBinBuffer
!= None and UniStringBinBuffer
.getvalue() != "":
2895 AutoFile
= PathClass(gAutoGenStringFormFileName
% {"module_name":self
.Name
}, self
.OutputDir
)
2896 self
._AutoGenFileList
[AutoFile
] = UniStringBinBuffer
.getvalue()
2897 AutoFile
.IsBinary
= True
2898 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
2899 if UniStringBinBuffer
!= None:
2900 UniStringBinBuffer
.close()
2901 return self
._AutoGenFileList
2903 ## Return the list of library modules explicitly or implicityly used by this module
2904 def _GetLibraryList(self
):
2905 if self
._DependentLibraryList
== None:
2906 # only merge library classes and PCD for non-library module
2908 self
._DependentLibraryList
= []
2910 if self
.AutoGenVersion
< 0x00010005:
2911 self
._DependentLibraryList
= self
.PlatformInfo
.ResolveLibraryReference(self
.Module
)
2913 self
._DependentLibraryList
= self
.PlatformInfo
.ApplyLibraryInstance(self
.Module
)
2914 return self
._DependentLibraryList
2917 def UpdateComments(Recver
, Src
):
2919 if Key
not in Recver
:
2921 Recver
[Key
].extend(Src
[Key
])
2922 ## Get the list of PCDs from current module
2924 # @retval list The list of PCD
2926 def _GetModulePcdList(self
):
2927 if self
._ModulePcdList
== None:
2928 # apply PCD settings from platform
2929 self
._ModulePcdList
= self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, self
.Module
.Pcds
)
2930 self
.UpdateComments(self
._PcdComments
, self
.Module
.PcdComments
)
2931 return self
._ModulePcdList
2933 ## Get the list of PCDs from dependent libraries
2935 # @retval list The list of PCD
2937 def _GetLibraryPcdList(self
):
2938 if self
._LibraryPcdList
== None:
2940 if not self
.IsLibrary
:
2941 # get PCDs from dependent libraries
2942 for Library
in self
.DependentLibraryList
:
2943 self
.UpdateComments(self
._PcdComments
, Library
.PcdComments
)
2944 for Key
in Library
.Pcds
:
2945 # skip duplicated PCDs
2946 if Key
in self
.Module
.Pcds
or Key
in Pcds
:
2948 Pcds
[Key
] = copy
.copy(Library
.Pcds
[Key
])
2949 # apply PCD settings from platform
2950 self
._LibraryPcdList
= self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, Pcds
)
2952 self
._LibraryPcdList
= []
2953 return self
._LibraryPcdList
2955 ## Get the GUID value mapping
2957 # @retval dict The mapping between GUID cname and its value
2959 def _GetGuidList(self
):
2960 if self
._GuidList
== None:
2961 self
._GuidList
= sdict()
2962 self
._GuidList
.update(self
.Module
.Guids
)
2963 for Library
in self
.DependentLibraryList
:
2964 self
._GuidList
.update(Library
.Guids
)
2965 self
.UpdateComments(self
._GuidComments
, Library
.GuidComments
)
2966 self
.UpdateComments(self
._GuidComments
, self
.Module
.GuidComments
)
2967 return self
._GuidList
2969 def GetGuidsUsedByPcd(self
):
2970 if self
._GuidsUsedByPcd
== None:
2971 self
._GuidsUsedByPcd
= sdict()
2972 self
._GuidsUsedByPcd
.update(self
.Module
.GetGuidsUsedByPcd())
2973 for Library
in self
.DependentLibraryList
:
2974 self
._GuidsUsedByPcd
.update(Library
.GetGuidsUsedByPcd())
2975 return self
._GuidsUsedByPcd
2976 ## Get the protocol value mapping
2978 # @retval dict The mapping between protocol cname and its value
2980 def _GetProtocolList(self
):
2981 if self
._ProtocolList
== None:
2982 self
._ProtocolList
= sdict()
2983 self
._ProtocolList
.update(self
.Module
.Protocols
)
2984 for Library
in self
.DependentLibraryList
:
2985 self
._ProtocolList
.update(Library
.Protocols
)
2986 self
.UpdateComments(self
._ProtocolComments
, Library
.ProtocolComments
)
2987 self
.UpdateComments(self
._ProtocolComments
, self
.Module
.ProtocolComments
)
2988 return self
._ProtocolList
2990 ## Get the PPI value mapping
2992 # @retval dict The mapping between PPI cname and its value
2994 def _GetPpiList(self
):
2995 if self
._PpiList
== None:
2996 self
._PpiList
= sdict()
2997 self
._PpiList
.update(self
.Module
.Ppis
)
2998 for Library
in self
.DependentLibraryList
:
2999 self
._PpiList
.update(Library
.Ppis
)
3000 self
.UpdateComments(self
._PpiComments
, Library
.PpiComments
)
3001 self
.UpdateComments(self
._PpiComments
, self
.Module
.PpiComments
)
3002 return self
._PpiList
3004 ## Get the list of include search path
3006 # @retval list The list path
3008 def _GetIncludePathList(self
):
3009 if self
._IncludePathList
== None:
3010 self
._IncludePathList
= []
3011 if self
.AutoGenVersion
< 0x00010005:
3012 for Inc
in self
.Module
.Includes
:
3013 if Inc
not in self
._IncludePathList
:
3014 self
._IncludePathList
.append(Inc
)
3016 Inc
= path
.join(Inc
, self
.Arch
.capitalize())
3017 if os
.path
.exists(Inc
) and Inc
not in self
._IncludePathList
:
3018 self
._IncludePathList
.append(Inc
)
3019 # Edk module needs to put DEBUG_DIR at the end of search path and not to use SOURCE_DIR all the time
3020 self
._IncludePathList
.append(self
.DebugDir
)
3022 self
._IncludePathList
.append(self
.MetaFile
.Dir
)
3023 self
._IncludePathList
.append(self
.DebugDir
)
3025 for Package
in self
.Module
.Packages
:
3026 PackageDir
= path
.join(self
.WorkspaceDir
, Package
.MetaFile
.Dir
)
3027 if PackageDir
not in self
._IncludePathList
:
3028 self
._IncludePathList
.append(PackageDir
)
3029 for Inc
in Package
.Includes
:
3030 if Inc
not in self
._IncludePathList
:
3031 self
._IncludePathList
.append(str(Inc
))
3032 return self
._IncludePathList
3034 ## Get HII EX PCDs which maybe used by VFR
3036 # efivarstore used by VFR may relate with HII EX PCDs
3037 # Get the variable name and GUID from efivarstore and HII EX PCD
3038 # List the HII EX PCDs in As Built INF if both name and GUID match.
3040 # @retval list HII EX PCDs
3042 def _GetPcdsMaybeUsedByVfr(self
):
3043 if not self
.SourceFileList
:
3047 for SrcFile
in self
.SourceFileList
:
3048 if SrcFile
.Ext
.lower() != '.vfr':
3050 Vfri
= os
.path
.join(self
.OutputDir
, SrcFile
.BaseName
+ '.i')
3051 if not os
.path
.exists(Vfri
):
3053 VfriFile
= open(Vfri
, 'r')
3054 Content
= VfriFile
.read()
3056 Pos
= Content
.find('efivarstore')
3059 # Make sure 'efivarstore' is the start of efivarstore statement
3060 # In case of the value of 'name' (name = efivarstore) is equal to 'efivarstore'
3063 while Index
>= 0 and Content
[Index
] in ' \t\r\n':
3065 if Index
>= 0 and Content
[Index
] != ';':
3066 Pos
= Content
.find('efivarstore', Pos
+ len('efivarstore'))
3069 # 'efivarstore' must be followed by name and guid
3071 Name
= gEfiVarStoreNamePattern
.search(Content
, Pos
)
3074 Guid
= gEfiVarStoreGuidPattern
.search(Content
, Pos
)
3077 NameArray
= ConvertStringToByteArray('L"' + Name
.group(1) + '"')
3078 NameGuids
.append((NameArray
, GuidStructureStringToGuidString(Guid
.group(1))))
3079 Pos
= Content
.find('efivarstore', Name
.end())
3083 for Pcd
in self
.PlatformInfo
.Platform
.Pcds
.values():
3084 if Pcd
.Type
!= TAB_PCDS_DYNAMIC_EX_HII
:
3086 for SkuName
in Pcd
.SkuInfoList
:
3087 SkuInfo
= Pcd
.SkuInfoList
[SkuName
]
3088 Name
= ConvertStringToByteArray(SkuInfo
.VariableName
)
3089 Value
= GuidValue(SkuInfo
.VariableGuid
, self
.PlatformInfo
.PackageList
)
3092 Guid
= GuidStructureStringToGuidString(Value
)
3093 if (Name
, Guid
) in NameGuids
and Pcd
not in HiiExPcds
:
3094 HiiExPcds
.append(Pcd
)
3099 ## Create AsBuilt INF file the module
3101 def CreateAsBuiltInf(self
):
3102 if self
.IsAsBuiltInfCreated
:
3105 # Skip the following code for EDK I inf
3106 if self
.AutoGenVersion
< 0x00010005:
3109 # Skip the following code for libraries
3113 # Skip the following code for modules with no source files
3114 if self
.SourceFileList
== None or self
.SourceFileList
== []:
3117 # Skip the following code for modules without any binary files
3118 if self
.BinaryFileList
<> None and self
.BinaryFileList
<> []:
3121 ### TODO: How to handles mixed source and binary modules
3123 # Find all DynamicEx and PatchableInModule PCDs used by this module and dependent libraries
3124 # Also find all packages that the DynamicEx PCDs depend on
3129 PcdTokenSpaceList
= []
3130 for Pcd
in self
.ModulePcdList
+ self
.LibraryPcdList
:
3131 if Pcd
.Type
== TAB_PCDS_PATCHABLE_IN_MODULE
:
3132 PatchablePcds
[Pcd
.TokenCName
] = Pcd
3133 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, 'PatchableInModule'))
3134 elif Pcd
.Type
in GenC
.gDynamicExPcd
:
3137 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, 'DynamicEx'))
3138 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, 'Dynamic'))
3139 PcdTokenSpaceList
.append(Pcd
.TokenSpaceGuidCName
)
3141 GuidList
.update(self
.GuidList
)
3142 for TokenSpace
in self
.GetGuidsUsedByPcd():
3143 # If token space is not referred by patch PCD or Ex PCD, remove the GUID from GUID list
3144 # The GUIDs in GUIDs section should really be the GUIDs in source INF or referred by Ex an patch PCDs
3145 if TokenSpace
not in PcdTokenSpaceList
and TokenSpace
in GuidList
:
3146 GuidList
.pop(TokenSpace
)
3147 CheckList
= (GuidList
, self
.PpiList
, self
.ProtocolList
, PcdCheckList
)
3148 for Package
in self
.DerivedPackageList
:
3149 if Package
in Packages
:
3151 BeChecked
= (Package
.Guids
, Package
.Ppis
, Package
.Protocols
, Package
.Pcds
)
3153 for Index
in range(len(BeChecked
)):
3154 for Item
in CheckList
[Index
]:
3155 if Item
in BeChecked
[Index
]:
3156 Packages
+= [Package
]
3161 VfrPcds
= self
._GetPcdsMaybeUsedByVfr
()
3162 for Pkg
in self
.PlatformInfo
.PackageList
:
3165 for VfrPcd
in VfrPcds
:
3166 if ((VfrPcd
.TokenCName
, VfrPcd
.TokenSpaceGuidCName
, 'DynamicEx') in Pkg
.Pcds
or
3167 (VfrPcd
.TokenCName
, VfrPcd
.TokenSpaceGuidCName
, 'Dynamic') in Pkg
.Pcds
):
3171 ModuleType
= self
.ModuleType
3172 if ModuleType
== 'UEFI_DRIVER' and self
.DepexGenerated
:
3173 ModuleType
= 'DXE_DRIVER'
3176 if self
.PcdIsDriver
!= '':
3177 DriverType
= self
.PcdIsDriver
3180 MDefs
= self
.Module
.Defines
3183 'module_name' : self
.Name
,
3184 'module_guid' : Guid
,
3185 'module_module_type' : ModuleType
,
3186 'module_version_string' : [MDefs
['VERSION_STRING']] if 'VERSION_STRING' in MDefs
else [],
3187 'pcd_is_driver_string' : [],
3188 'module_uefi_specification_version' : [],
3189 'module_pi_specification_version' : [],
3190 'module_entry_point' : self
.Module
.ModuleEntryPointList
,
3191 'module_unload_image' : self
.Module
.ModuleUnloadImageList
,
3192 'module_constructor' : self
.Module
.ConstructorList
,
3193 'module_destructor' : self
.Module
.DestructorList
,
3194 'module_shadow' : [MDefs
['SHADOW']] if 'SHADOW' in MDefs
else [],
3195 'module_pci_vendor_id' : [MDefs
['PCI_VENDOR_ID']] if 'PCI_VENDOR_ID' in MDefs
else [],
3196 'module_pci_device_id' : [MDefs
['PCI_DEVICE_ID']] if 'PCI_DEVICE_ID' in MDefs
else [],
3197 'module_pci_class_code' : [MDefs
['PCI_CLASS_CODE']] if 'PCI_CLASS_CODE' in MDefs
else [],
3198 'module_pci_revision' : [MDefs
['PCI_REVISION']] if 'PCI_REVISION' in MDefs
else [],
3199 'module_build_number' : [MDefs
['BUILD_NUMBER']] if 'BUILD_NUMBER' in MDefs
else [],
3200 'module_spec' : [MDefs
['SPEC']] if 'SPEC' in MDefs
else [],
3201 'module_uefi_hii_resource_section' : [MDefs
['UEFI_HII_RESOURCE_SECTION']] if 'UEFI_HII_RESOURCE_SECTION' in MDefs
else [],
3202 'module_uni_file' : [MDefs
['MODULE_UNI_FILE']] if 'MODULE_UNI_FILE' in MDefs
else [],
3203 'module_arch' : self
.Arch
,
3204 'package_item' : ['%s' % (Package
.MetaFile
.File
.replace('\\','/')) for Package
in Packages
],
3206 'patchablepcd_item' : [],
3208 'protocol_item' : [],
3212 'libraryclasses_item' : []
3215 if self
.AutoGenVersion
> int(gInfSpecVersion
, 0):
3216 AsBuiltInfDict
['module_inf_version'] = '0x%08x' % self
.AutoGenVersion
3218 AsBuiltInfDict
['module_inf_version'] = gInfSpecVersion
3221 AsBuiltInfDict
['pcd_is_driver_string'] += [DriverType
]
3223 if 'UEFI_SPECIFICATION_VERSION' in self
.Specification
:
3224 AsBuiltInfDict
['module_uefi_specification_version'] += [self
.Specification
['UEFI_SPECIFICATION_VERSION']]
3225 if 'PI_SPECIFICATION_VERSION' in self
.Specification
:
3226 AsBuiltInfDict
['module_pi_specification_version'] += [self
.Specification
['PI_SPECIFICATION_VERSION']]
3228 OutputDir
= self
.OutputDir
.replace('\\','/').strip('/')
3229 if self
.ModuleType
in ['BASE', 'USER_DEFINED']:
3230 for Item
in self
.CodaTargetList
:
3231 File
= Item
.Target
.Path
.replace('\\','/').strip('/').replace(OutputDir
,'').strip('/')
3232 if Item
.Target
.Ext
.lower() == '.aml':
3233 AsBuiltInfDict
['binary_item'] += ['ASL|' + File
]
3234 elif Item
.Target
.Ext
.lower() == '.acpi':
3235 AsBuiltInfDict
['binary_item'] += ['ACPI|' + File
]
3237 AsBuiltInfDict
['binary_item'] += ['BIN|' + File
]
3239 for Item
in self
.CodaTargetList
:
3240 File
= Item
.Target
.Path
.replace('\\','/').strip('/').replace(OutputDir
,'').strip('/')
3241 if Item
.Target
.Ext
.lower() == '.efi':
3242 AsBuiltInfDict
['binary_item'] += ['PE32|' + self
.Name
+ '.efi']
3244 AsBuiltInfDict
['binary_item'] += ['BIN|' + File
]
3245 if self
.DepexGenerated
:
3246 if self
.ModuleType
in ['PEIM']:
3247 AsBuiltInfDict
['binary_item'] += ['PEI_DEPEX|' + self
.Name
+ '.depex']
3248 if self
.ModuleType
in ['DXE_DRIVER','DXE_RUNTIME_DRIVER','DXE_SAL_DRIVER','UEFI_DRIVER']:
3249 AsBuiltInfDict
['binary_item'] += ['DXE_DEPEX|' + self
.Name
+ '.depex']
3250 if self
.ModuleType
in ['DXE_SMM_DRIVER']:
3251 AsBuiltInfDict
['binary_item'] += ['SMM_DEPEX|' + self
.Name
+ '.depex']
3253 for Root
, Dirs
, Files
in os
.walk(OutputDir
):
3255 if File
.lower().endswith('.pdb'):
3256 AsBuiltInfDict
['binary_item'] += ['DISPOSABLE|' + File
]
3257 HeaderComments
= self
.Module
.HeaderComments
3259 for Index
in range(len(HeaderComments
)):
3260 if HeaderComments
[Index
].find('@BinaryHeader') != -1:
3261 HeaderComments
[Index
] = HeaderComments
[Index
].replace('@BinaryHeader', '@file')
3264 AsBuiltInfDict
['header_comments'] = '\n'.join(HeaderComments
[StartPos
:]).replace(':#', '://')
3265 AsBuiltInfDict
['tail_comments'] = '\n'.join(self
.Module
.TailComments
)
3268 (self
.ProtocolList
, self
._ProtocolComments
, 'protocol_item'),
3269 (self
.PpiList
, self
._PpiComments
, 'ppi_item'),
3270 (GuidList
, self
._GuidComments
, 'guid_item')
3272 for Item
in GenList
:
3273 for CName
in Item
[0]:
3275 if CName
in Item
[1]:
3276 Comments
= '\n '.join(Item
[1][CName
])
3279 Entry
= Comments
+ '\n ' + CName
3280 AsBuiltInfDict
[Item
[2]].append(Entry
)
3281 PatchList
= parsePcdInfoFromMapFile(
3282 os
.path
.join(self
.OutputDir
, self
.Name
+ '.map'),
3283 os
.path
.join(self
.OutputDir
, self
.Name
+ '.efi')
3286 for PatchPcd
in PatchList
:
3287 if PatchPcd
[0] not in PatchablePcds
:
3289 Pcd
= PatchablePcds
[PatchPcd
[0]]
3291 if Pcd
.DatumType
!= 'VOID*':
3292 HexFormat
= '0x%02x'
3293 if Pcd
.DatumType
== 'UINT16':
3294 HexFormat
= '0x%04x'
3295 elif Pcd
.DatumType
== 'UINT32':
3296 HexFormat
= '0x%08x'
3297 elif Pcd
.DatumType
== 'UINT64':
3298 HexFormat
= '0x%016x'
3299 PcdValue
= HexFormat
% int(Pcd
.DefaultValue
, 0)
3301 if Pcd
.MaxDatumSize
== None or Pcd
.MaxDatumSize
== '':
3302 EdkLogger
.error("build", AUTOGEN_ERROR
,
3303 "Unknown [MaxDatumSize] of PCD [%s.%s]" % (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
)
3305 ArraySize
= int(Pcd
.MaxDatumSize
, 0)
3306 PcdValue
= Pcd
.DefaultValue
3307 if PcdValue
[0] != '{':
3309 if PcdValue
[0] == 'L':
3311 PcdValue
= PcdValue
.lstrip('L')
3312 PcdValue
= eval(PcdValue
)
3314 for Index
in range(0, len(PcdValue
)):
3316 CharVal
= ord(PcdValue
[Index
])
3317 NewValue
= NewValue
+ '0x%02x' % (CharVal
& 0x00FF) + ', ' \
3318 + '0x%02x' % (CharVal
>> 8) + ', '
3320 NewValue
= NewValue
+ '0x%02x' % (ord(PcdValue
[Index
]) % 0x100) + ', '
3323 Padding
= Padding
* 2
3324 ArraySize
= ArraySize
/ 2
3325 if ArraySize
< (len(PcdValue
) + 1):
3326 EdkLogger
.error("build", AUTOGEN_ERROR
,
3327 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
)
3329 if ArraySize
> len(PcdValue
) + 1:
3330 NewValue
= NewValue
+ Padding
* (ArraySize
- len(PcdValue
) - 1)
3331 PcdValue
= NewValue
+ Padding
.strip().rstrip(',') + '}'
3332 elif len(PcdValue
.split(',')) <= ArraySize
:
3333 PcdValue
= PcdValue
.rstrip('}') + ', 0x00' * (ArraySize
- len(PcdValue
.split(',')))
3336 EdkLogger
.error("build", AUTOGEN_ERROR
,
3337 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
)
3339 PcdItem
= '%s.%s|%s|0x%X' % \
3340 (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
, PcdValue
, PatchPcd
[1])
3342 if (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in self
._PcdComments
:
3343 PcdComments
= '\n '.join(self
._PcdComments
[Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
])
3345 PcdItem
= PcdComments
+ '\n ' + PcdItem
3346 AsBuiltInfDict
['patchablepcd_item'].append(PcdItem
)
3349 for Pcd
in Pcds
+ VfrPcds
:
3354 if Pcd
.Type
== TAB_PCDS_DYNAMIC_EX_HII
:
3355 for SkuName
in Pcd
.SkuInfoList
:
3356 SkuInfo
= Pcd
.SkuInfoList
[SkuName
]
3357 SkuId
= SkuInfo
.SkuId
3358 HiiInfo
= '## %s|%s|%s' % (SkuInfo
.VariableName
, SkuInfo
.VariableGuid
, SkuInfo
.VariableOffset
)
3362 # Don't generate duplicated HII PCD
3364 if (SkuId
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in HiiPcds
:
3367 HiiPcds
.append((SkuId
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
3368 if (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in self
._PcdComments
:
3369 PcdCommentList
= self
._PcdComments
[Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
][:]
3373 for Index
, Comment
in enumerate(PcdCommentList
):
3374 for Usage
in UsageList
:
3375 if Comment
.find(Usage
) != -1:
3379 if UsageIndex
!= -1:
3380 PcdCommentList
[UsageIndex
] = '## %s %s %s' % (UsageStr
, HiiInfo
, PcdCommentList
[UsageIndex
].replace(UsageStr
, ''))
3382 PcdCommentList
.append('## UNDEFINED ' + HiiInfo
)
3383 PcdComments
= '\n '.join(PcdCommentList
)
3384 PcdEntry
= Pcd
.TokenSpaceGuidCName
+ '.' + Pcd
.TokenCName
3386 PcdEntry
= PcdComments
+ '\n ' + PcdEntry
3387 AsBuiltInfDict
['pcd_item'] += [PcdEntry
]
3388 for Item
in self
.BuildOption
:
3389 if 'FLAGS' in self
.BuildOption
[Item
]:
3390 AsBuiltInfDict
['flags_item'] += ['%s:%s_%s_%s_%s_FLAGS = %s' % (self
.ToolChainFamily
, self
.BuildTarget
, self
.ToolChain
, self
.Arch
, Item
, self
.BuildOption
[Item
]['FLAGS'].strip())]
3392 # Generated LibraryClasses section in comments.
3393 for Library
in self
.LibraryAutoGenList
:
3394 AsBuiltInfDict
['libraryclasses_item'] += [Library
.MetaFile
.File
.replace('\\', '/')]
3396 # Generated depex expression section in comments.
3397 AsBuiltInfDict
['depexsection_item'] = ''
3398 DepexExpresion
= self
._GetDepexExpresionString
()
3400 AsBuiltInfDict
['depexsection_item'] = DepexExpresion
3402 AsBuiltInf
= TemplateString()
3403 AsBuiltInf
.Append(gAsBuiltInfHeaderString
.Replace(AsBuiltInfDict
))
3405 SaveFileOnChange(os
.path
.join(self
.OutputDir
, self
.Name
+ '.inf'), str(AsBuiltInf
), False)
3407 self
.IsAsBuiltInfCreated
= True
3409 ## Create makefile for the module and its dependent libraries
3411 # @param CreateLibraryMakeFile Flag indicating if or not the makefiles of
3412 # dependent libraries will be created
3414 def CreateMakeFile(self
, CreateLibraryMakeFile
=True):
3415 # Ignore generating makefile when it is a binary module
3416 if self
.IsBinaryModule
:
3419 if self
.IsMakeFileCreated
:
3422 if not self
.IsLibrary
and CreateLibraryMakeFile
:
3423 for LibraryAutoGen
in self
.LibraryAutoGenList
:
3424 LibraryAutoGen
.CreateMakeFile()
3426 if len(self
.CustomMakefile
) == 0:
3427 Makefile
= GenMake
.ModuleMakefile(self
)
3429 Makefile
= GenMake
.CustomMakefile(self
)
3430 if Makefile
.Generate():
3431 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated makefile for module %s [%s]" %
3432 (self
.Name
, self
.Arch
))
3434 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of makefile for module %s [%s]" %
3435 (self
.Name
, self
.Arch
))
3437 self
.IsMakeFileCreated
= True
3439 def CopyBinaryFiles(self
):
3440 for File
in self
.Module
.Binaries
:
3442 DstPath
= os
.path
.join(self
.OutputDir
, os
.path
.basename(SrcPath
))
3443 CopyLongFilePath(SrcPath
, DstPath
)
3444 ## Create autogen code for the module and its dependent libraries
3446 # @param CreateLibraryCodeFile Flag indicating if or not the code of
3447 # dependent libraries will be created
3449 def CreateCodeFile(self
, CreateLibraryCodeFile
=True):
3450 if self
.IsCodeFileCreated
:
3453 # Need to generate PcdDatabase even PcdDriver is binarymodule
3454 if self
.IsBinaryModule
and self
.PcdIsDriver
!= '':
3455 CreatePcdDatabaseCode(self
, TemplateString(), TemplateString())
3457 if self
.IsBinaryModule
:
3459 self
.CopyBinaryFiles()
3462 if not self
.IsLibrary
and CreateLibraryCodeFile
:
3463 for LibraryAutoGen
in self
.LibraryAutoGenList
:
3464 LibraryAutoGen
.CreateCodeFile()
3467 IgoredAutoGenList
= []
3469 for File
in self
.AutoGenFileList
:
3470 if GenC
.Generate(File
.Path
, self
.AutoGenFileList
[File
], File
.IsBinary
):
3471 #Ignore Edk AutoGen.c
3472 if self
.AutoGenVersion
< 0x00010005 and File
.Name
== 'AutoGen.c':
3475 AutoGenList
.append(str(File
))
3477 IgoredAutoGenList
.append(str(File
))
3479 # Skip the following code for EDK I inf
3480 if self
.AutoGenVersion
< 0x00010005:
3483 for ModuleType
in self
.DepexList
:
3484 # Ignore empty [depex] section or [depex] section for "USER_DEFINED" module
3485 if len(self
.DepexList
[ModuleType
]) == 0 or ModuleType
== "USER_DEFINED":
3488 Dpx
= GenDepex
.DependencyExpression(self
.DepexList
[ModuleType
], ModuleType
, True)
3489 DpxFile
= gAutoGenDepexFileName
% {"module_name" : self
.Name
}
3491 if len(Dpx
.PostfixNotation
) <> 0:
3492 self
.DepexGenerated
= True
3494 if Dpx
.Generate(path
.join(self
.OutputDir
, DpxFile
)):
3495 AutoGenList
.append(str(DpxFile
))
3497 IgoredAutoGenList
.append(str(DpxFile
))
3499 if IgoredAutoGenList
== []:
3500 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] files for module %s [%s]" %
3501 (" ".join(AutoGenList
), self
.Name
, self
.Arch
))
3502 elif AutoGenList
== []:
3503 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of [%s] files for module %s [%s]" %
3504 (" ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
3506 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] (skipped %s) files for module %s [%s]" %
3507 (" ".join(AutoGenList
), " ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
3509 self
.IsCodeFileCreated
= True
3512 ## Summarize the ModuleAutoGen objects of all libraries used by this module
3513 def _GetLibraryAutoGenList(self
):
3514 if self
._LibraryAutoGenList
== None:
3515 self
._LibraryAutoGenList
= []
3516 for Library
in self
.DependentLibraryList
:
3523 self
.PlatformInfo
.MetaFile
3525 if La
not in self
._LibraryAutoGenList
:
3526 self
._LibraryAutoGenList
.append(La
)
3527 for Lib
in La
.CodaTargetList
:
3528 self
._ApplyBuildRule
(Lib
.Target
, TAB_UNKNOWN_FILE
)
3529 return self
._LibraryAutoGenList
3531 Module
= property(_GetModule
)
3532 Name
= property(_GetBaseName
)
3533 Guid
= property(_GetGuid
)
3534 Version
= property(_GetVersion
)
3535 ModuleType
= property(_GetModuleType
)
3536 ComponentType
= property(_GetComponentType
)
3537 BuildType
= property(_GetBuildType
)
3538 PcdIsDriver
= property(_GetPcdIsDriver
)
3539 AutoGenVersion
= property(_GetAutoGenVersion
)
3540 Macros
= property(_GetMacros
)
3541 Specification
= property(_GetSpecification
)
3543 IsLibrary
= property(_IsLibrary
)
3544 IsBinaryModule
= property(_IsBinaryModule
)
3545 BuildDir
= property(_GetBuildDir
)
3546 OutputDir
= property(_GetOutputDir
)
3547 DebugDir
= property(_GetDebugDir
)
3548 MakeFileDir
= property(_GetMakeFileDir
)
3549 CustomMakefile
= property(_GetCustomMakefile
)
3551 IncludePathList
= property(_GetIncludePathList
)
3552 AutoGenFileList
= property(_GetAutoGenFileList
)
3553 UnicodeFileList
= property(_GetUnicodeFileList
)
3554 SourceFileList
= property(_GetSourceFileList
)
3555 BinaryFileList
= property(_GetBinaryFiles
) # FileType : [File List]
3556 Targets
= property(_GetTargets
)
3557 IntroTargetList
= property(_GetIntroTargetList
)
3558 CodaTargetList
= property(_GetFinalTargetList
)
3559 FileTypes
= property(_GetFileTypes
)
3560 BuildRules
= property(_GetBuildRules
)
3562 DependentPackageList
= property(_GetDependentPackageList
)
3563 DependentLibraryList
= property(_GetLibraryList
)
3564 LibraryAutoGenList
= property(_GetLibraryAutoGenList
)
3565 DerivedPackageList
= property(_GetDerivedPackageList
)
3567 ModulePcdList
= property(_GetModulePcdList
)
3568 LibraryPcdList
= property(_GetLibraryPcdList
)
3569 GuidList
= property(_GetGuidList
)
3570 ProtocolList
= property(_GetProtocolList
)
3571 PpiList
= property(_GetPpiList
)
3572 DepexList
= property(_GetDepexTokenList
)
3573 DxsFile
= property(_GetDxsFile
)
3574 DepexExpressionList
= property(_GetDepexExpressionTokenList
)
3575 BuildOption
= property(_GetModuleBuildOption
)
3576 BuildOptionIncPathList
= property(_GetBuildOptionIncPathList
)
3577 BuildCommand
= property(_GetBuildCommand
)
3579 FixedAtBuildPcds
= property(_GetFixedAtBuildPcds
)
3581 # This acts like the main() function for the script, unless it is 'import'ed into another script.
3582 if __name__
== '__main__':