2 # Generate AutoGen.h, AutoGen.c and *.depex files
4 # Copyright (c) 2007 - 2010, 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.
18 import os
.path
as path
24 from StringIO
import StringIO
26 from StrGather
import *
27 from BuildEngine
import BuildRule
29 from Common
.BuildToolError
import *
30 from Common
.DataType
import *
31 from Common
.Misc
import *
32 from Common
.String
import *
33 import Common
.GlobalData
as GlobalData
34 from GenFds
.FdfParser
import *
35 from CommonDataClass
.CommonClass
import SkuInfoClass
36 from Workspace
.BuildClassObject
import *
37 import Common
.VpdInfoFile
as VpdInfoFile
39 ## Regular expression for splitting Dependency Expression stirng into tokens
40 gDepexTokenPattern
= re
.compile("(\(|\)|\w+| \S+\.inf)")
42 ## Mapping Makefile type
43 gMakeTypeMap
= {"MSFT":"nmake", "GCC":"gmake"}
46 ## Build rule configuration file
47 gBuildRuleFile
= 'Conf/build_rule.txt'
49 ## default file name for AutoGen
50 gAutoGenCodeFileName
= "AutoGen.c"
51 gAutoGenHeaderFileName
= "AutoGen.h"
52 gAutoGenStringFileName
= "%(module_name)sStrDefs.h"
53 gAutoGenStringFormFileName
= "%(module_name)sStrDefs.hpk"
54 gAutoGenDepexFileName
= "%(module_name)s.depex"
56 ## Base class for AutoGen
58 # This class just implements the cache mechanism of AutoGen objects.
60 class AutoGen(object):
61 # database to maintain the objects of xxxAutoGen
62 _CACHE_
= {} # (BuildTarget, ToolChain) : {ARCH : {platform file: AutoGen object}}}
66 # @param Class class object of real AutoGen class
67 # (WorkspaceAutoGen, ModuleAutoGen or PlatformAutoGen)
68 # @param Workspace Workspace directory or WorkspaceAutoGen object
69 # @param MetaFile The path of meta file
70 # @param Target Build target
71 # @param Toolchain Tool chain name
72 # @param Arch Target arch
73 # @param *args The specific class related parameters
74 # @param **kwargs The specific class related dict parameters
76 def __new__(Class
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
77 # check if the object has been created
78 Key
= (Target
, Toolchain
)
79 if Key
not in Class
._CACHE
_ or Arch
not in Class
._CACHE
_[Key
] \
80 or MetaFile
not in Class
._CACHE
_[Key
][Arch
]:
81 AutoGenObject
= super(AutoGen
, Class
).__new
__(Class
)
82 # call real constructor
83 if not AutoGenObject
._Init
(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
85 if Key
not in Class
._CACHE
_:
86 Class
._CACHE
_[Key
] = {}
87 if Arch
not in Class
._CACHE
_[Key
]:
88 Class
._CACHE
_[Key
][Arch
] = {}
89 Class
._CACHE
_[Key
][Arch
][MetaFile
] = AutoGenObject
91 AutoGenObject
= Class
._CACHE
_[Key
][Arch
][MetaFile
]
97 # The file path of platform file will be used to represent hash value of this object
99 # @retval int Hash value of the file path of platform file
102 return hash(self
.MetaFile
)
106 # The file path of platform file will be used to represent this object
108 # @retval string String of platform file path
111 return str(self
.MetaFile
)
114 def __eq__(self
, Other
):
115 return Other
and self
.MetaFile
== Other
117 ## Workspace AutoGen class
119 # This class is used mainly to control the whole platform build for different
120 # architecture. This class will generate top level makefile.
122 class WorkspaceAutoGen(AutoGen
):
123 ## Real constructor of WorkspaceAutoGen
125 # This method behaves the same as __init__ except that it needs explict invoke
126 # (in super class's __new__ method)
128 # @param WorkspaceDir Root directory of workspace
129 # @param ActivePlatform Meta-file of active platform
130 # @param Target Build target
131 # @param Toolchain Tool chain name
132 # @param ArchList List of architecture of current build
133 # @param MetaFileDb Database containing meta-files
134 # @param BuildConfig Configuration of build
135 # @param ToolDefinition Tool chain definitions
136 # @param FlashDefinitionFile File of flash definition
137 # @param Fds FD list to be generated
138 # @param Fvs FV list to be generated
139 # @param SkuId SKU id from command line
141 def _Init(self
, WorkspaceDir
, ActivePlatform
, Target
, Toolchain
, ArchList
, MetaFileDb
,
142 BuildConfig
, ToolDefinition
, FlashDefinitionFile
='', Fds
=[], Fvs
=[], SkuId
='', UniFlag
=None):
143 self
.MetaFile
= ActivePlatform
.MetaFile
144 self
.WorkspaceDir
= WorkspaceDir
145 self
.Platform
= ActivePlatform
146 self
.BuildTarget
= Target
147 self
.ToolChain
= Toolchain
148 self
.ArchList
= ArchList
150 self
.UniFlag
= UniFlag
152 self
.BuildDatabase
= MetaFileDb
153 self
.TargetTxt
= BuildConfig
154 self
.ToolDef
= ToolDefinition
155 self
.FdfFile
= FlashDefinitionFile
156 self
.FdTargetList
= Fds
157 self
.FvTargetList
= Fvs
158 self
.AutoGenObjectList
= []
160 # there's many relative directory operations, so ...
161 os
.chdir(self
.WorkspaceDir
)
163 # parse FDF file to get PCDs in it, if any
164 if self
.FdfFile
!= None and self
.FdfFile
!= '':
165 Fdf
= FdfParser(self
.FdfFile
.Path
)
167 PcdSet
= Fdf
.Profile
.PcdDict
168 ModuleList
= Fdf
.Profile
.InfList
169 self
.FdfProfile
= Fdf
.Profile
173 self
.FdfProfile
= None
175 # apply SKU and inject PCDs from Flash Definition file
176 for Arch
in self
.ArchList
:
177 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
]
178 Platform
.SkuName
= self
.SkuId
179 for Name
, Guid
in PcdSet
:
180 Platform
.AddPcd(Name
, Guid
, PcdSet
[Name
, Guid
])
182 Pa
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
184 # Explicitly collect platform's dynamic PCDs
186 Pa
.CollectPlatformDynamicPcds()
187 self
.AutoGenObjectList
.append(Pa
)
189 self
._BuildDir
= None
191 self
._MakeFileDir
= None
192 self
._BuildCommand
= None
197 return "%s [%s]" % (self
.MetaFile
, ", ".join(self
.ArchList
))
199 ## Return the directory to store FV files
201 if self
._FvDir
== None:
202 self
._FvDir
= path
.join(self
.BuildDir
, 'FV')
205 ## Return the directory to store all intermediate and final files built
206 def _GetBuildDir(self
):
207 return self
.AutoGenObjectList
[0].BuildDir
209 ## Return the build output directory platform specifies
210 def _GetOutputDir(self
):
211 return self
.Platform
.OutputDirectory
213 ## Return platform name
215 return self
.Platform
.PlatformName
217 ## Return meta-file GUID
219 return self
.Platform
.Guid
221 ## Return platform version
222 def _GetVersion(self
):
223 return self
.Platform
.Version
225 ## Return paths of tools
226 def _GetToolDefinition(self
):
227 return self
.AutoGenObjectList
[0].ToolDefinition
229 ## Return directory of platform makefile
231 # @retval string Makefile directory
233 def _GetMakeFileDir(self
):
234 if self
._MakeFileDir
== None:
235 self
._MakeFileDir
= self
.BuildDir
236 return self
._MakeFileDir
238 ## Return build command string
240 # @retval string Build command string
242 def _GetBuildCommand(self
):
243 if self
._BuildCommand
== None:
244 # BuildCommand should be all the same. So just get one from platform AutoGen
245 self
._BuildCommand
= self
.AutoGenObjectList
[0].BuildCommand
246 return self
._BuildCommand
248 ## Create makefile for the platform and modules in it
250 # @param CreateDepsMakeFile Flag indicating if the makefile for
251 # modules will be created as well
253 def CreateMakeFile(self
, CreateDepsMakeFile
=False):
254 # create makefile for platform
255 Makefile
= GenMake
.TopLevelMakefile(self
)
256 if Makefile
.Generate():
257 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated makefile for platform [%s] %s\n" %
258 (self
.MetaFile
, self
.ArchList
))
260 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of makefile for platform [%s] %s\n" %
261 (self
.MetaFile
, self
.ArchList
))
263 if CreateDepsMakeFile
:
264 for Pa
in self
.AutoGenObjectList
:
265 Pa
.CreateMakeFile(CreateDepsMakeFile
)
267 ## Create autogen code for platform and modules
269 # Since there's no autogen code for platform, this method will do nothing
270 # if CreateModuleCodeFile is set to False.
272 # @param CreateDepsCodeFile Flag indicating if creating module's
273 # autogen code file or not
275 def CreateCodeFile(self
, CreateDepsCodeFile
=False):
276 if not CreateDepsCodeFile
:
278 for Pa
in self
.AutoGenObjectList
:
279 Pa
.CreateCodeFile(CreateDepsCodeFile
)
281 Name
= property(_GetName
)
282 Guid
= property(_GetGuid
)
283 Version
= property(_GetVersion
)
284 OutputDir
= property(_GetOutputDir
)
286 ToolDefinition
= property(_GetToolDefinition
) # toolcode : tool path
288 BuildDir
= property(_GetBuildDir
)
289 FvDir
= property(_GetFvDir
)
290 MakeFileDir
= property(_GetMakeFileDir
)
291 BuildCommand
= property(_GetBuildCommand
)
293 ## AutoGen class for platform
295 # PlatformAutoGen class will process the original information in platform
296 # file in order to generate makefile for platform.
298 class PlatformAutoGen(AutoGen
):
300 # Used to store all PCDs for both PEI and DXE phase, in order to generate
301 # correct PCD database
304 _NonDynaPcdList_
= []
306 ## The real constructor of PlatformAutoGen
308 # This method is not supposed to be called by users of PlatformAutoGen. It's
309 # only used by factory method __new__() to do real initialization work for an
310 # object of PlatformAutoGen
312 # @param Workspace WorkspaceAutoGen object
313 # @param PlatformFile Platform file (DSC file)
314 # @param Target Build target (DEBUG, RELEASE)
315 # @param Toolchain Name of tool chain
316 # @param Arch arch of the platform supports
318 def _Init(self
, Workspace
, PlatformFile
, Target
, Toolchain
, Arch
):
319 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen platform [%s] [%s]" % (PlatformFile
, Arch
))
320 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (PlatformFile
, Arch
, Toolchain
, Target
)
322 self
.MetaFile
= PlatformFile
323 self
.Workspace
= Workspace
324 self
.WorkspaceDir
= Workspace
.WorkspaceDir
325 self
.ToolChain
= Toolchain
326 self
.BuildTarget
= Target
328 self
.SourceDir
= PlatformFile
.SubDir
329 self
.SourceOverrideDir
= None
330 self
.FdTargetList
= self
.Workspace
.FdTargetList
331 self
.FvTargetList
= self
.Workspace
.FvTargetList
334 # flag indicating if the makefile/C-code file has been created or not
335 self
.IsMakeFileCreated
= False
336 self
.IsCodeFileCreated
= False
338 self
._Platform
= None
343 self
._BuildRule
= None
344 self
._SourceDir
= None
345 self
._BuildDir
= None
346 self
._OutputDir
= None
348 self
._MakeFileDir
= None
351 self
._PcdTokenNumber
= None # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
352 self
._DynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
353 self
._NonDynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
355 self
._ToolDefinitions
= None
356 self
._ToolDefFile
= None # toolcode : tool path
357 self
._ToolChainFamily
= None
358 self
._BuildRuleFamily
= None
359 self
._BuildOption
= None # toolcode : option
360 self
._EdkBuildOption
= None # edktoolcode : option
361 self
._EdkIIBuildOption
= None # edkiitoolcode : option
362 self
._PackageList
= None
363 self
._ModuleAutoGenList
= None
364 self
._LibraryAutoGenList
= None
365 self
._BuildCommand
= None
367 # get the original module/package/platform objects
368 self
.BuildDatabase
= Workspace
.BuildDatabase
372 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
374 ## Create autogen code for platform and modules
376 # Since there's no autogen code for platform, this method will do nothing
377 # if CreateModuleCodeFile is set to False.
379 # @param CreateModuleCodeFile Flag indicating if creating module's
380 # autogen code file or not
382 def CreateCodeFile(self
, CreateModuleCodeFile
=False):
383 # only module has code to be greated, so do nothing if CreateModuleCodeFile is False
384 if self
.IsCodeFileCreated
or not CreateModuleCodeFile
:
387 for Ma
in self
.ModuleAutoGenList
:
388 Ma
.CreateCodeFile(True)
390 # don't do this twice
391 self
.IsCodeFileCreated
= True
393 ## Create makefile for the platform and mdoules in it
395 # @param CreateModuleMakeFile Flag indicating if the makefile for
396 # modules will be created as well
398 def CreateMakeFile(self
, CreateModuleMakeFile
=False):
399 if CreateModuleMakeFile
:
400 for ModuleFile
in self
.Platform
.Modules
:
401 Ma
= ModuleAutoGen(self
.Workspace
, ModuleFile
, self
.BuildTarget
,
402 self
.ToolChain
, self
.Arch
, self
.MetaFile
)
403 Ma
.CreateMakeFile(True)
405 # no need to create makefile for the platform more than once
406 if self
.IsMakeFileCreated
:
409 # create makefile for platform
410 Makefile
= GenMake
.PlatformMakefile(self
)
411 if Makefile
.Generate():
412 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated makefile for platform [%s] [%s]\n" %
413 (self
.MetaFile
, self
.Arch
))
415 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of makefile for platform [%s] [%s]\n" %
416 (self
.MetaFile
, self
.Arch
))
417 self
.IsMakeFileCreated
= True
419 ## Collect dynamic PCDs
421 # Gather dynamic PCDs list from each module and their settings from platform
422 # This interface should be invoked explicitly when platform action is created.
424 def CollectPlatformDynamicPcds(self
):
425 # for gathering error information
426 NoDatumTypePcdList
= set()
429 for F
in self
.Platform
.Modules
.keys():
430 M
= ModuleAutoGen(self
.Workspace
, F
, self
.BuildTarget
, self
.ToolChain
, self
.Arch
, self
.MetaFile
)
431 #GuidValue.update(M.Guids)
433 self
.Platform
.Modules
[F
].M
= M
435 for PcdFromModule
in M
.ModulePcdList
+M
.LibraryPcdList
:
436 # make sure that the "VOID*" kind of datum has MaxDatumSize set
437 if PcdFromModule
.DatumType
== "VOID*" and PcdFromModule
.MaxDatumSize
== None:
438 NoDatumTypePcdList
.add("%s.%s [%s]" % (PcdFromModule
.TokenSpaceGuidCName
, PcdFromModule
.TokenCName
, F
))
440 if PcdFromModule
.Type
in GenC
.gDynamicPcd
or PcdFromModule
.Type
in GenC
.gDynamicExPcd
:
442 # If a dynamic PCD used by a PEM module/PEI module & DXE module,
443 # it should be stored in Pcd PEI database, If a dynamic only
444 # used by DXE module, it should be stored in DXE PCD database.
445 # The default Phase is DXE
447 if M
.ModuleType
in ["PEIM", "PEI_CORE"]:
448 PcdFromModule
.Phase
= "PEI"
449 if PcdFromModule
not in self
._DynaPcdList
_:
450 self
._DynaPcdList
_.append(PcdFromModule
)
451 elif PcdFromModule
.Phase
== 'PEI':
452 # overwrite any the same PCD existing, if Phase is PEI
453 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
454 self
._DynaPcdList
_[Index
] = PcdFromModule
455 elif PcdFromModule
not in self
._NonDynaPcdList
_:
456 self
._NonDynaPcdList
_.append(PcdFromModule
)
458 # print out error information and break the build, if error found
459 if len(NoDatumTypePcdList
) > 0:
460 NoDatumTypePcdListString
= "\n\t\t".join(NoDatumTypePcdList
)
461 EdkLogger
.error("build", AUTOGEN_ERROR
, "PCD setting error",
463 ExtraData
="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"
464 % NoDatumTypePcdListString
)
465 self
._NonDynamicPcdList
= self
._NonDynaPcdList
_
466 self
._DynamicPcdList
= self
._DynaPcdList
_
467 self
.AllPcdList
= self
._NonDynamicPcdList
+ self
._DynamicPcdList
470 # Sort dynamic PCD list to:
471 # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should
472 # try to be put header of dynamicd List
473 # 2) If PCD is HII type, the PCD item should be put after unicode type PCD
475 # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.
480 VpdFile
= VpdInfoFile
.VpdInfoFile()
481 NeedProcessVpdMapFile
= False
483 if (self
.Workspace
.ArchList
[-1] == self
.Arch
):
484 for Pcd
in self
._DynamicPcdList
:
486 # just pick the a value to determine whether is unicode string type
487 Sku
= Pcd
.SkuInfoList
[Pcd
.SkuInfoList
.keys()[0]]
488 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
490 PcdValue
= Sku
.DefaultValue
491 if Pcd
.DatumType
== 'VOID*' and PcdValue
.startswith("L"):
492 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
493 UnicodePcdArray
.append(Pcd
)
494 elif len(Sku
.VariableName
) > 0:
495 # if found HII type PCD then insert to right of UnicodeIndex
496 HiiPcdArray
.append(Pcd
)
498 OtherPcdArray
.append(Pcd
)
500 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
501 if not (self
.Platform
.VpdToolGuid
== None or self
.Platform
.VpdToolGuid
== ''):
503 # Fix the optional data of VPD PCD.
505 if (Pcd
.DatumType
.strip() != "VOID*"):
506 if Sku
.DefaultValue
== '':
507 Pcd
.SkuInfoList
[Pcd
.SkuInfoList
.keys()[0]].DefaultValue
= Pcd
.MaxDatumSize
508 Pcd
.MaxDatumSize
= None
510 EdkLogger
.error("build", AUTOGEN_ERROR
, "PCD setting error",
512 ExtraData
="\n\tPCD: %s.%s format incorrect in DSC: %s\n\t\t\n"
513 % (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
, self
.Platform
.MetaFile
.Path
))
515 VpdFile
.Add(Pcd
, Sku
.VpdOffset
)
516 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
517 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== "*":
518 NeedProcessVpdMapFile
= True
521 # Fix the PCDs define in VPD PCD section that never referenced by module.
522 # An example is PCD for signature usage.
524 for DscPcd
in self
.Platform
.Pcds
:
525 DscPcdEntry
= self
.Platform
.Pcds
[DscPcd
]
526 if DscPcdEntry
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
527 if not (self
.Platform
.VpdToolGuid
== None or self
.Platform
.VpdToolGuid
== ''):
529 for VpdPcd
in VpdFile
._VpdArray
.keys():
530 # This PCD has been referenced by module
531 if (VpdPcd
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
532 (VpdPcd
.TokenCName
== DscPcdEntry
.TokenCName
):
535 # Not found, it should be signature
537 # just pick the a value to determine whether is unicode string type
538 Sku
= DscPcdEntry
.SkuInfoList
[DscPcdEntry
.SkuInfoList
.keys()[0]]
539 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
541 # Need to iterate DEC pcd information to get the value & datumtype
542 for eachDec
in self
.PackageList
:
543 for DecPcd
in eachDec
.Pcds
:
544 DecPcdEntry
= eachDec
.Pcds
[DecPcd
]
545 if (DecPcdEntry
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
546 (DecPcdEntry
.TokenCName
== DscPcdEntry
.TokenCName
):
547 DscPcdEntry
.DatumType
= DecPcdEntry
.DatumType
548 DscPcdEntry
.DefaultValue
= DecPcdEntry
.DefaultValue
549 Sku
.DefaultValue
= DecPcdEntry
.DefaultValue
551 VpdFile
.Add(DscPcdEntry
, Sku
.VpdOffset
)
552 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
553 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== "*":
554 NeedProcessVpdMapFile
= True
557 if (self
.Platform
.FlashDefinition
== None or self
.Platform
.FlashDefinition
== '') and \
558 VpdFile
.GetCount() != 0:
559 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
,
560 "Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD." % str(self
.Platform
.MetaFile
))
562 if VpdFile
.GetCount() != 0:
563 WorkspaceDb
= self
.BuildDatabase
.WorkspaceDb
564 DscTimeStamp
= WorkspaceDb
.GetTimeStamp(WorkspaceDb
.GetFileId(str(self
.Platform
.MetaFile
)))
565 FvPath
= os
.path
.join(self
.BuildDir
, "FV")
566 if not os
.path
.exists(FvPath
):
570 EdkLogger
.error("build", FILE_WRITE_FAILURE
, "Fail to create FV folder under %s" % self
.BuildDir
)
572 VpdFileName
= self
.Platform
.VpdFileName
573 if VpdFileName
== None or VpdFileName
== "" :
574 VpdFilePath
= os
.path
.join(FvPath
, "%s.txt" % self
.Platform
.VpdToolGuid
)
576 VpdFilePath
= os
.path
.join(FvPath
, "%s.txt" % VpdFileName
)
578 if not os
.path
.exists(VpdFilePath
) or os
.path
.getmtime(VpdFilePath
) < DscTimeStamp
:
579 VpdFile
.Write(VpdFilePath
)
581 # retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.
583 for ToolDef
in self
.ToolDefinition
.values():
584 if ToolDef
.has_key("GUID") and ToolDef
["GUID"] == self
.Platform
.VpdToolGuid
:
585 if not ToolDef
.has_key("PATH"):
586 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
, "PATH attribute was not provided for BPDG guid tool %s in tools_def.txt" % self
.Platform
.VpdToolGuid
)
587 BPDGToolName
= ToolDef
["PATH"]
589 # Call third party GUID BPDG tool.
590 if BPDGToolName
!= None:
591 VpdInfoFile
.CallExtenalBPDGTool(BPDGToolName
, VpdFilePath
, VpdFileName
)
593 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.")
595 # Process VPD map file generated by third party BPDG tool
596 if NeedProcessVpdMapFile
:
597 if VpdFileName
== None or VpdFileName
== "" :
598 VpdMapFilePath
= os
.path
.join(self
.BuildDir
, "FV", "%s.map" % self
.Platform
.VpdToolGuid
)
600 VpdMapFilePath
= os
.path
.join(self
.BuildDir
, "FV", "%s.map" % VpdFileName
)
601 if os
.path
.exists(VpdMapFilePath
):
602 VpdFile
.Read(VpdMapFilePath
)
605 for Pcd
in self
._DynamicPcdList
:
606 # just pick the a value to determine whether is unicode string type
607 Sku
= Pcd
.SkuInfoList
[Pcd
.SkuInfoList
.keys()[0]]
608 if Sku
.VpdOffset
== "*":
609 Sku
.VpdOffset
= VpdFile
.GetOffset(Pcd
)[0]
611 EdkLogger
.error("build", FILE_READ_FAILURE
, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath
)
613 # Delete the DynamicPcdList At the last time enter into this function
614 del self
._DynamicPcdList
[:]
615 self
._DynamicPcdList
.extend(UnicodePcdArray
)
616 self
._DynamicPcdList
.extend(HiiPcdArray
)
617 self
._DynamicPcdList
.extend(OtherPcdArray
)
620 ## Return the platform build data object
621 def _GetPlatform(self
):
622 if self
._Platform
== None:
623 self
._Platform
= self
.BuildDatabase
[self
.MetaFile
, self
.Arch
]
624 return self
._Platform
626 ## Return platform name
628 return self
.Platform
.PlatformName
630 ## Return the meta file GUID
632 return self
.Platform
.Guid
634 ## Return the platform version
635 def _GetVersion(self
):
636 return self
.Platform
.Version
638 ## Return the FDF file name
639 def _GetFdfFile(self
):
640 if self
._FdfFile
== None:
641 if self
.Workspace
.FdfFile
!= "":
642 self
._FdfFile
= path
.join(self
.WorkspaceDir
, self
.Workspace
.FdfFile
)
647 ## Return the build output directory platform specifies
648 def _GetOutputDir(self
):
649 return self
.Platform
.OutputDirectory
651 ## Return the directory to store all intermediate and final files built
652 def _GetBuildDir(self
):
653 if self
._BuildDir
== None:
654 if os
.path
.isabs(self
.OutputDir
):
655 self
._BuildDir
= path
.join(
656 path
.abspath(self
.OutputDir
),
657 self
.BuildTarget
+ "_" + self
.ToolChain
,
660 self
._BuildDir
= path
.join(
663 self
.BuildTarget
+ "_" + self
.ToolChain
,
665 return self
._BuildDir
667 ## Return directory of platform makefile
669 # @retval string Makefile directory
671 def _GetMakeFileDir(self
):
672 if self
._MakeFileDir
== None:
673 self
._MakeFileDir
= path
.join(self
.BuildDir
, self
.Arch
)
674 return self
._MakeFileDir
676 ## Return build command string
678 # @retval string Build command string
680 def _GetBuildCommand(self
):
681 if self
._BuildCommand
== None:
682 self
._BuildCommand
= []
683 if "MAKE" in self
.ToolDefinition
and "PATH" in self
.ToolDefinition
["MAKE"]:
684 self
._BuildCommand
+= SplitOption(self
.ToolDefinition
["MAKE"]["PATH"])
685 if "FLAGS" in self
.ToolDefinition
["MAKE"]:
686 NewOption
= self
.ToolDefinition
["MAKE"]["FLAGS"].strip()
688 self
._BuildCommand
+= SplitOption(NewOption
)
689 return self
._BuildCommand
691 ## Get tool chain definition
693 # Get each tool defition for given tool chain from tools_def.txt and platform
695 def _GetToolDefinition(self
):
696 if self
._ToolDefinitions
== None:
697 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDictionary
698 if TAB_TOD_DEFINES_COMMAND_TYPE
not in self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
:
699 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
, "No tools found in configuration",
700 ExtraData
="[%s]" % self
.MetaFile
)
701 self
._ToolDefinitions
= {}
703 for Def
in ToolDefinition
:
704 Target
, Tag
, Arch
, Tool
, Attr
= Def
.split("_")
705 if Target
!= self
.BuildTarget
or Tag
!= self
.ToolChain
or Arch
!= self
.Arch
:
708 Value
= ToolDefinition
[Def
]
709 # don't record the DLL
711 DllPathList
.add(Value
)
714 if Tool
not in self
._ToolDefinitions
:
715 self
._ToolDefinitions
[Tool
] = {}
716 self
._ToolDefinitions
[Tool
][Attr
] = Value
720 if GlobalData
.gOptions
.SilentMode
and "MAKE" in self
._ToolDefinitions
:
721 if "FLAGS" not in self
._ToolDefinitions
["MAKE"]:
722 self
._ToolDefinitions
["MAKE"]["FLAGS"] = ""
723 self
._ToolDefinitions
["MAKE"]["FLAGS"] += " -s"
725 for Tool
in self
._ToolDefinitions
:
726 for Attr
in self
._ToolDefinitions
[Tool
]:
727 Value
= self
._ToolDefinitions
[Tool
][Attr
]
728 if Tool
in self
.BuildOption
and Attr
in self
.BuildOption
[Tool
]:
729 # check if override is indicated
730 if self
.BuildOption
[Tool
][Attr
].startswith('='):
731 Value
= self
.BuildOption
[Tool
][Attr
][1:]
733 Value
+= " " + self
.BuildOption
[Tool
][Attr
]
736 # Don't put MAKE definition in the file
740 ToolsDef
+= "%s = %s\n" % (Tool
, Value
)
742 # Don't put MAKE definition in the file
747 ToolsDef
+= "%s_%s = %s\n" % (Tool
, Attr
, Value
)
750 SaveFileOnChange(self
.ToolDefinitionFile
, ToolsDef
)
751 for DllPath
in DllPathList
:
752 os
.environ
["PATH"] = DllPath
+ os
.pathsep
+ os
.environ
["PATH"]
753 os
.environ
["MAKE_FLAGS"] = MakeFlags
755 return self
._ToolDefinitions
757 ## Return the paths of tools
758 def _GetToolDefFile(self
):
759 if self
._ToolDefFile
== None:
760 self
._ToolDefFile
= os
.path
.join(self
.MakeFileDir
, "TOOLS_DEF." + self
.Arch
)
761 return self
._ToolDefFile
763 ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
764 def _GetToolChainFamily(self
):
765 if self
._ToolChainFamily
== None:
766 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
767 if TAB_TOD_DEFINES_FAMILY
not in ToolDefinition \
768 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_FAMILY
] \
769 or not ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]:
770 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
772 self
._ToolChainFamily
= "MSFT"
774 self
._ToolChainFamily
= ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]
775 return self
._ToolChainFamily
777 def _GetBuildRuleFamily(self
):
778 if self
._BuildRuleFamily
== None:
779 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
780 if TAB_TOD_DEFINES_BUILDRULEFAMILY
not in ToolDefinition \
781 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
] \
782 or not ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]:
783 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
785 self
._BuildRuleFamily
= "MSFT"
787 self
._BuildRuleFamily
= ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]
788 return self
._BuildRuleFamily
790 ## Return the build options specific for all modules in this platform
791 def _GetBuildOptions(self
):
792 if self
._BuildOption
== None:
793 self
._BuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
)
794 return self
._BuildOption
796 ## Return the build options specific for EDK modules in this platform
797 def _GetEdkBuildOptions(self
):
798 if self
._EdkBuildOption
== None:
799 self
._EdkBuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDK_NAME
)
800 return self
._EdkBuildOption
802 ## Return the build options specific for EDKII modules in this platform
803 def _GetEdkIIBuildOptions(self
):
804 if self
._EdkIIBuildOption
== None:
805 self
._EdkIIBuildOption
= self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDKII_NAME
)
806 return self
._EdkIIBuildOption
808 ## Parse build_rule.txt in $(WORKSPACE)/Conf/build_rule.txt
810 # @retval BuildRule object
812 def _GetBuildRule(self
):
813 if self
._BuildRule
== None:
815 if TAB_TAT_DEFINES_BUILD_RULE_CONF
in self
.Workspace
.TargetTxt
.TargetTxtDictionary
:
816 BuildRuleFile
= self
.Workspace
.TargetTxt
.TargetTxtDictionary
[TAB_TAT_DEFINES_BUILD_RULE_CONF
]
817 if BuildRuleFile
in [None, '']:
818 BuildRuleFile
= gBuildRuleFile
819 self
._BuildRule
= BuildRule(BuildRuleFile
)
820 return self
._BuildRule
822 ## Summarize the packages used by modules in this platform
823 def _GetPackageList(self
):
824 if self
._PackageList
== None:
825 self
._PackageList
= set()
826 for La
in self
.LibraryAutoGenList
:
827 self
._PackageList
.update(La
.DependentPackageList
)
828 for Ma
in self
.ModuleAutoGenList
:
829 self
._PackageList
.update(Ma
.DependentPackageList
)
830 self
._PackageList
= list(self
._PackageList
)
831 return self
._PackageList
833 ## Get list of non-dynamic PCDs
834 def _GetNonDynamicPcdList(self
):
835 if self
._NonDynamicPcdList
== None:
836 self
.CollectPlatformDynamicPcds()
837 return self
._NonDynamicPcdList
839 ## Get list of dynamic PCDs
840 def _GetDynamicPcdList(self
):
841 if self
._DynamicPcdList
== None:
842 self
.CollectPlatformDynamicPcds()
843 return self
._DynamicPcdList
845 ## Generate Token Number for all PCD
846 def _GetPcdTokenNumbers(self
):
847 if self
._PcdTokenNumber
== None:
848 self
._PcdTokenNumber
= sdict()
850 for Pcd
in self
.DynamicPcdList
:
851 if Pcd
.Phase
== "PEI":
852 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
853 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
856 for Pcd
in self
.DynamicPcdList
:
857 if Pcd
.Phase
== "DXE":
858 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
859 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
862 for Pcd
in self
.NonDynamicPcdList
:
863 self
._PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
865 return self
._PcdTokenNumber
867 ## Summarize ModuleAutoGen objects of all modules/libraries to be built for this platform
868 def _GetAutoGenObjectList(self
):
869 self
._ModuleAutoGenList
= []
870 self
._LibraryAutoGenList
= []
871 for ModuleFile
in self
.Platform
.Modules
:
880 if Ma
not in self
._ModuleAutoGenList
:
881 self
._ModuleAutoGenList
.append(Ma
)
882 for La
in Ma
.LibraryAutoGenList
:
883 if La
not in self
._LibraryAutoGenList
:
884 self
._LibraryAutoGenList
.append(La
)
886 ## Summarize ModuleAutoGen objects of all modules to be built for this platform
887 def _GetModuleAutoGenList(self
):
888 if self
._ModuleAutoGenList
== None:
889 self
._GetAutoGenObjectList
()
890 return self
._ModuleAutoGenList
892 ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
893 def _GetLibraryAutoGenList(self
):
894 if self
._LibraryAutoGenList
== None:
895 self
._GetAutoGenObjectList
()
896 return self
._LibraryAutoGenList
898 ## Test if a module is supported by the platform
900 # An error will be raised directly if the module or its arch is not supported
901 # by the platform or current configuration
903 def ValidModule(self
, Module
):
904 return Module
in self
.Platform
.Modules
or Module
in self
.Platform
.LibraryInstances
906 ## Resolve the library classes in a module to library instances
908 # This method will not only resolve library classes but also sort the library
909 # instances according to the dependency-ship.
911 # @param Module The module from which the library classes will be resolved
913 # @retval library_list List of library instances sorted
915 def ApplyLibraryInstance(self
, Module
):
916 ModuleType
= Module
.ModuleType
918 # for overridding library instances with module specific setting
919 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
921 # add forced library instances (specified under LibraryClasses sections)
922 for LibraryClass
in self
.Platform
.LibraryClasses
.GetKeys():
923 if LibraryClass
.startswith("NULL"):
924 Module
.LibraryClasses
[LibraryClass
] = self
.Platform
.LibraryClasses
[LibraryClass
]
926 # add forced library instances (specified in module overrides)
927 for LibraryClass
in PlatformModule
.LibraryClasses
:
928 if LibraryClass
.startswith("NULL"):
929 Module
.LibraryClasses
[LibraryClass
] = PlatformModule
.LibraryClasses
[LibraryClass
]
932 LibraryConsumerList
= [Module
]
934 ConsumedByList
= sdict()
935 LibraryInstance
= sdict()
937 EdkLogger
.verbose("")
938 EdkLogger
.verbose("Library instances of module [%s] [%s]:" % (str(Module
), self
.Arch
))
939 while len(LibraryConsumerList
) > 0:
940 M
= LibraryConsumerList
.pop()
941 for LibraryClassName
in M
.LibraryClasses
:
942 if LibraryClassName
not in LibraryInstance
:
943 # override library instance for this module
944 if LibraryClassName
in PlatformModule
.LibraryClasses
:
945 LibraryPath
= PlatformModule
.LibraryClasses
[LibraryClassName
]
947 LibraryPath
= self
.Platform
.LibraryClasses
[LibraryClassName
, ModuleType
]
948 if LibraryPath
== None or LibraryPath
== "":
949 LibraryPath
= M
.LibraryClasses
[LibraryClassName
]
950 if LibraryPath
== None or LibraryPath
== "":
951 EdkLogger
.error("build", RESOURCE_NOT_AVAILABLE
,
952 "Instance of library class [%s] is not found" % LibraryClassName
,
954 ExtraData
="in [%s] [%s]\n\tconsumed by module [%s]" % (str(M
), self
.Arch
, str(Module
)))
956 LibraryModule
= self
.BuildDatabase
[LibraryPath
, self
.Arch
]
957 # for those forced library instance (NULL library), add a fake library class
958 if LibraryClassName
.startswith("NULL"):
959 LibraryModule
.LibraryClass
.append(LibraryClassObject(LibraryClassName
, [ModuleType
]))
960 elif LibraryModule
.LibraryClass
== None \
961 or len(LibraryModule
.LibraryClass
) == 0 \
962 or (ModuleType
!= 'USER_DEFINED'
963 and ModuleType
not in LibraryModule
.LibraryClass
[0].SupModList
):
964 # only USER_DEFINED can link against any library instance despite of its SupModList
965 EdkLogger
.error("build", OPTION_MISSING
,
966 "Module type [%s] is not supported by library instance [%s]" \
967 % (ModuleType
, LibraryPath
), File
=self
.MetaFile
,
968 ExtraData
="consumed by [%s]" % str(Module
))
970 LibraryInstance
[LibraryClassName
] = LibraryModule
971 LibraryConsumerList
.append(LibraryModule
)
972 EdkLogger
.verbose("\t" + str(LibraryClassName
) + " : " + str(LibraryModule
))
974 LibraryModule
= LibraryInstance
[LibraryClassName
]
976 if LibraryModule
== None:
979 if LibraryModule
.ConstructorList
!= [] and LibraryModule
not in Constructor
:
980 Constructor
.append(LibraryModule
)
982 if LibraryModule
not in ConsumedByList
:
983 ConsumedByList
[LibraryModule
] = []
984 # don't add current module itself to consumer list
986 if M
in ConsumedByList
[LibraryModule
]:
988 ConsumedByList
[LibraryModule
].append(M
)
990 # Initialize the sorted output list to the empty set
992 SortedLibraryList
= []
994 # Q <- Set of all nodes with no incoming edges
996 LibraryList
= [] #LibraryInstance.values()
998 for LibraryClassName
in LibraryInstance
:
999 M
= LibraryInstance
[LibraryClassName
]
1000 LibraryList
.append(M
)
1001 if ConsumedByList
[M
] == []:
1005 # start the DAG algorithm
1009 while Q
== [] and EdgeRemoved
:
1011 # for each node Item with a Constructor
1012 for Item
in LibraryList
:
1013 if Item
not in Constructor
:
1015 # for each Node without a constructor with an edge e from Item to Node
1016 for Node
in ConsumedByList
[Item
]:
1017 if Node
in Constructor
:
1019 # remove edge e from the graph if Node has no constructor
1020 ConsumedByList
[Item
].remove(Node
)
1022 if ConsumedByList
[Item
] == []:
1023 # insert Item into Q
1028 # DAG is done if there's no more incoming edge for all nodes
1032 # remove node from Q
1035 SortedLibraryList
.append(Node
)
1037 # for each node Item with an edge e from Node to Item do
1038 for Item
in LibraryList
:
1039 if Node
not in ConsumedByList
[Item
]:
1041 # remove edge e from the graph
1042 ConsumedByList
[Item
].remove(Node
)
1044 if ConsumedByList
[Item
] != []:
1046 # insert Item into Q, if Item has no other incoming edges
1050 # if any remaining node Item in the graph has a constructor and an incoming edge, then the graph has a cycle
1052 for Item
in LibraryList
:
1053 if ConsumedByList
[Item
] != [] and Item
in Constructor
and len(Constructor
) > 1:
1054 ErrorMessage
= "\tconsumed by " + "\n\tconsumed by ".join([str(L
) for L
in ConsumedByList
[Item
]])
1055 EdkLogger
.error("build", BUILD_ERROR
, 'Library [%s] with constructors has a cycle' % str(Item
),
1056 ExtraData
=ErrorMessage
, File
=self
.MetaFile
)
1057 if Item
not in SortedLibraryList
:
1058 SortedLibraryList
.append(Item
)
1061 # Build the list of constructor and destructir names
1062 # The DAG Topo sort produces the destructor order, so the list of constructors must generated in the reverse order
1064 SortedLibraryList
.reverse()
1065 return SortedLibraryList
1068 ## Override PCD setting (type, value, ...)
1070 # @param ToPcd The PCD to be overrided
1071 # @param FromPcd The PCD overrideing from
1073 def _OverridePcd(self
, ToPcd
, FromPcd
, Module
=""):
1075 # in case there's PCDs coming from FDF file, which have no type given.
1076 # at this point, ToPcd.Type has the type found from dependent
1080 if ToPcd
.Pending
and FromPcd
.Type
not in [None, '']:
1081 ToPcd
.Type
= FromPcd
.Type
1082 elif (ToPcd
.Type
not in [None, '']) and (FromPcd
.Type
not in [None, ''])\
1083 and (ToPcd
.Type
!= FromPcd
.Type
) and (ToPcd
.Type
in FromPcd
.Type
):
1084 if ToPcd
.Type
.strip() == "DynamicEx":
1085 ToPcd
.Type
= FromPcd
.Type
1086 elif ToPcd
.Type
not in [None, ''] and FromPcd
.Type
not in [None, ''] \
1087 and ToPcd
.Type
!= FromPcd
.Type
:
1088 EdkLogger
.error("build", OPTION_CONFLICT
, "Mismatched PCD type",
1089 ExtraData
="%s.%s is defined as [%s] in module %s, but as [%s] in platform."\
1090 % (ToPcd
.TokenSpaceGuidCName
, ToPcd
.TokenCName
,
1091 ToPcd
.Type
, Module
, FromPcd
.Type
),
1094 if FromPcd
.MaxDatumSize
not in [None, '']:
1095 ToPcd
.MaxDatumSize
= FromPcd
.MaxDatumSize
1096 if FromPcd
.DefaultValue
not in [None, '']:
1097 ToPcd
.DefaultValue
= FromPcd
.DefaultValue
1098 if FromPcd
.TokenValue
not in [None, '']:
1099 ToPcd
.TokenValue
= FromPcd
.TokenValue
1100 if FromPcd
.MaxDatumSize
not in [None, '']:
1101 ToPcd
.MaxDatumSize
= FromPcd
.MaxDatumSize
1102 if FromPcd
.DatumType
not in [None, '']:
1103 ToPcd
.DatumType
= FromPcd
.DatumType
1104 if FromPcd
.SkuInfoList
not in [None, '', []]:
1105 ToPcd
.SkuInfoList
= FromPcd
.SkuInfoList
1107 # check the validation of datum
1108 IsValid
, Cause
= CheckPcdDatum(ToPcd
.DatumType
, ToPcd
.DefaultValue
)
1110 EdkLogger
.error('build', FORMAT_INVALID
, Cause
, File
=self
.MetaFile
,
1111 ExtraData
="%s.%s" % (ToPcd
.TokenSpaceGuidCName
, ToPcd
.TokenCName
))
1113 if ToPcd
.DatumType
== "VOID*" and ToPcd
.MaxDatumSize
in ['', None]:
1114 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "No MaxDatumSize specified for PCD %s.%s" \
1115 % (ToPcd
.TokenSpaceGuidCName
, ToPcd
.TokenCName
))
1116 Value
= ToPcd
.DefaultValue
1117 if Value
in [None, '']:
1118 ToPcd
.MaxDatumSize
= 1
1119 elif Value
[0] == 'L':
1120 ToPcd
.MaxDatumSize
= str(len(Value
) * 2)
1121 elif Value
[0] == '{':
1122 ToPcd
.MaxDatumSize
= str(len(Value
.split(',')))
1124 ToPcd
.MaxDatumSize
= str(len(Value
))
1126 # apply default SKU for dynamic PCDS if specified one is not available
1127 if (ToPcd
.Type
in PCD_DYNAMIC_TYPE_LIST
or ToPcd
.Type
in PCD_DYNAMIC_EX_TYPE_LIST
) \
1128 and ToPcd
.SkuInfoList
in [None, {}, '']:
1129 if self
.Platform
.SkuName
in self
.Platform
.SkuIds
:
1130 SkuName
= self
.Platform
.SkuName
1133 ToPcd
.SkuInfoList
= {
1134 SkuName
: SkuInfoClass(SkuName
, self
.Platform
.SkuIds
[SkuName
], '', '', '', '', '', ToPcd
.DefaultValue
)
1137 ## Apply PCD setting defined platform to a module
1139 # @param Module The module from which the PCD setting will be overrided
1141 # @retval PCD_list The list PCDs with settings from platform
1143 def ApplyPcdSetting(self
, Module
, Pcds
):
1144 # for each PCD in module
1145 for Name
,Guid
in Pcds
:
1146 PcdInModule
= Pcds
[Name
,Guid
]
1147 # find out the PCD setting in platform
1148 if (Name
,Guid
) in self
.Platform
.Pcds
:
1149 PcdInPlatform
= self
.Platform
.Pcds
[Name
,Guid
]
1151 PcdInPlatform
= None
1152 # then override the settings if any
1153 self
._OverridePcd
(PcdInModule
, PcdInPlatform
, Module
)
1154 # resolve the VariableGuid value
1155 for SkuId
in PcdInModule
.SkuInfoList
:
1156 Sku
= PcdInModule
.SkuInfoList
[SkuId
]
1157 if Sku
.VariableGuid
== '': continue
1158 Sku
.VariableGuidValue
= GuidValue(Sku
.VariableGuid
, self
.PackageList
)
1159 if Sku
.VariableGuidValue
== None:
1160 PackageList
= "\n\t".join([str(P
) for P
in self
.PackageList
])
1163 RESOURCE_NOT_AVAILABLE
,
1164 "Value of GUID [%s] is not found in" % Sku
.VariableGuid
,
1165 ExtraData
=PackageList
+ "\n\t(used with %s.%s from module %s)" \
1166 % (Guid
, Name
, str(Module
)),
1170 # override PCD settings with module specific setting
1171 if Module
in self
.Platform
.Modules
:
1172 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
1173 for Key
in PlatformModule
.Pcds
:
1175 self
._OverridePcd
(Pcds
[Key
], PlatformModule
.Pcds
[Key
], Module
)
1176 return Pcds
.values()
1178 ## Resolve library names to library modules
1180 # (for R8.x modules)
1182 # @param Module The module from which the library names will be resolved
1184 # @retval library_list The list of library modules
1186 def ResolveLibraryReference(self
, Module
):
1187 EdkLogger
.verbose("")
1188 EdkLogger
.verbose("Library instances of module [%s] [%s]:" % (str(Module
), self
.Arch
))
1189 LibraryConsumerList
= [Module
]
1191 # "CompilerStub" is a must for R8 modules
1192 if Module
.Libraries
:
1193 Module
.Libraries
.append("CompilerStub")
1195 while len(LibraryConsumerList
) > 0:
1196 M
= LibraryConsumerList
.pop()
1197 for LibraryName
in M
.Libraries
:
1198 Library
= self
.Platform
.LibraryClasses
[LibraryName
, ':dummy:']
1200 for Key
in self
.Platform
.LibraryClasses
.data
.keys():
1201 if LibraryName
.upper() == Key
.upper():
1202 Library
= self
.Platform
.LibraryClasses
[Key
, ':dummy:']
1205 EdkLogger
.warn("build", "Library [%s] is not found" % LibraryName
, File
=str(M
),
1206 ExtraData
="\t%s [%s]" % (str(Module
), self
.Arch
))
1209 if Library
not in LibraryList
:
1210 LibraryList
.append(Library
)
1211 LibraryConsumerList
.append(Library
)
1212 EdkLogger
.verbose("\t" + LibraryName
+ " : " + str(Library
) + ' ' + str(type(Library
)))
1215 ## Expand * in build option key
1217 # @param Options Options to be expanded
1219 # @retval options Options expanded
1221 def _ExpandBuildOption(self
, Options
, ModuleStyle
=None):
1226 if ModuleStyle
!= None and len (Key
) > 2:
1227 # Check Module style is EDK or EDKII.
1228 # Only append build option for the matched style module.
1229 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
1231 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
1234 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
1235 # if tool chain family doesn't match, skip it
1236 if Tool
in self
.ToolDefinition
and Family
!= "":
1237 FamilyIsNull
= False
1238 if self
.ToolDefinition
[Tool
].get(TAB_TOD_DEFINES_BUILDRULEFAMILY
, "") != "":
1239 if Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_BUILDRULEFAMILY
]:
1241 elif Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
1244 # expand any wildcard
1245 if Target
== "*" or Target
== self
.BuildTarget
:
1246 if Tag
== "*" or Tag
== self
.ToolChain
:
1247 if Arch
== "*" or Arch
== self
.Arch
:
1248 if Tool
not in BuildOptions
:
1249 BuildOptions
[Tool
] = {}
1250 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
]:
1251 BuildOptions
[Tool
][Attr
] = Options
[Key
]
1253 # append options for the same tool
1254 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
1255 # Build Option Family has been checked, which need't to be checked again for family.
1256 if FamilyMatch
or FamilyIsNull
:
1260 if ModuleStyle
!= None and len (Key
) > 2:
1261 # Check Module style is EDK or EDKII.
1262 # Only append build option for the matched style module.
1263 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
1265 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
1268 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
1269 # if tool chain family doesn't match, skip it
1270 if Tool
not in self
.ToolDefinition
or Family
=="":
1272 # option has been added before
1273 if Family
!= self
.ToolDefinition
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
1276 # expand any wildcard
1277 if Target
== "*" or Target
== self
.BuildTarget
:
1278 if Tag
== "*" or Tag
== self
.ToolChain
:
1279 if Arch
== "*" or Arch
== self
.Arch
:
1280 if Tool
not in BuildOptions
:
1281 BuildOptions
[Tool
] = {}
1282 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
]:
1283 BuildOptions
[Tool
][Attr
] = Options
[Key
]
1285 # append options for the same tool
1286 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
1289 ## Append build options in platform to a module
1291 # @param Module The module to which the build options will be appened
1293 # @retval options The options appended with build options in platform
1295 def ApplyBuildOption(self
, Module
):
1296 # Get the different options for the different style module
1297 if Module
.AutoGenVersion
< 0x00010005:
1298 PlatformOptions
= self
.EdkBuildOption
1300 PlatformOptions
= self
.EdkIIBuildOption
1301 ModuleOptions
= self
._ExpandBuildOption
(Module
.BuildOptions
)
1302 if Module
in self
.Platform
.Modules
:
1303 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
1304 PlatformModuleOptions
= self
._ExpandBuildOption
(PlatformModule
.BuildOptions
)
1306 PlatformModuleOptions
= {}
1308 AllTools
= set(ModuleOptions
.keys() + PlatformOptions
.keys() + PlatformModuleOptions
.keys() + self
.ToolDefinition
.keys())
1310 for Tool
in AllTools
:
1311 if Tool
not in BuildOptions
:
1312 BuildOptions
[Tool
] = {}
1314 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, PlatformModuleOptions
]:
1315 if Tool
not in Options
:
1317 for Attr
in Options
[Tool
]:
1318 Value
= Options
[Tool
][Attr
]
1319 if Attr
not in BuildOptions
[Tool
]:
1320 BuildOptions
[Tool
][Attr
] = ""
1321 # check if override is indicated
1322 if Value
.startswith('='):
1323 BuildOptions
[Tool
][Attr
] = Value
[1:]
1325 BuildOptions
[Tool
][Attr
] += " " + Value
1326 if Module
.AutoGenVersion
< 0x00010005 and self
.Workspace
.UniFlag
!= None:
1328 # Override UNI flag only for EDK module.
1330 if 'BUILD' not in BuildOptions
:
1331 BuildOptions
['BUILD'] = {}
1332 BuildOptions
['BUILD']['FLAGS'] = self
.Workspace
.UniFlag
1335 Platform
= property(_GetPlatform
)
1336 Name
= property(_GetName
)
1337 Guid
= property(_GetGuid
)
1338 Version
= property(_GetVersion
)
1340 OutputDir
= property(_GetOutputDir
)
1341 BuildDir
= property(_GetBuildDir
)
1342 MakeFileDir
= property(_GetMakeFileDir
)
1343 FdfFile
= property(_GetFdfFile
)
1345 PcdTokenNumber
= property(_GetPcdTokenNumbers
) # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
1346 DynamicPcdList
= property(_GetDynamicPcdList
) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1347 NonDynamicPcdList
= property(_GetNonDynamicPcdList
) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1348 PackageList
= property(_GetPackageList
)
1350 ToolDefinition
= property(_GetToolDefinition
) # toolcode : tool path
1351 ToolDefinitionFile
= property(_GetToolDefFile
) # toolcode : lib path
1352 ToolChainFamily
= property(_GetToolChainFamily
)
1353 BuildRuleFamily
= property(_GetBuildRuleFamily
)
1354 BuildOption
= property(_GetBuildOptions
) # toolcode : option
1355 EdkBuildOption
= property(_GetEdkBuildOptions
) # edktoolcode : option
1356 EdkIIBuildOption
= property(_GetEdkIIBuildOptions
) # edkiitoolcode : option
1358 BuildCommand
= property(_GetBuildCommand
)
1359 BuildRule
= property(_GetBuildRule
)
1360 ModuleAutoGenList
= property(_GetModuleAutoGenList
)
1361 LibraryAutoGenList
= property(_GetLibraryAutoGenList
)
1363 ## ModuleAutoGen class
1365 # This class encapsules the AutoGen behaviors for the build tools. In addition to
1366 # the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according
1367 # to the [depex] section in module's inf file.
1369 class ModuleAutoGen(AutoGen
):
1370 ## The real constructor of ModuleAutoGen
1372 # This method is not supposed to be called by users of ModuleAutoGen. It's
1373 # only used by factory method __new__() to do real initialization work for an
1374 # object of ModuleAutoGen
1376 # @param Workspace EdkIIWorkspaceBuild object
1377 # @param ModuleFile The path of module file
1378 # @param Target Build target (DEBUG, RELEASE)
1379 # @param Toolchain Name of tool chain
1380 # @param Arch The arch the module supports
1381 # @param PlatformFile Platform meta-file
1383 def _Init(self
, Workspace
, ModuleFile
, Target
, Toolchain
, Arch
, PlatformFile
):
1384 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen module [%s] [%s]" % (ModuleFile
, Arch
))
1385 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (ModuleFile
, Arch
, Toolchain
, Target
)
1387 self
.Workspace
= Workspace
1388 self
.WorkspaceDir
= Workspace
.WorkspaceDir
1390 self
.MetaFile
= ModuleFile
1391 self
.PlatformInfo
= PlatformAutoGen(Workspace
, PlatformFile
, Target
, Toolchain
, Arch
)
1392 # check if this module is employed by active platform
1393 if not self
.PlatformInfo
.ValidModule(self
.MetaFile
):
1394 EdkLogger
.verbose("Module [%s] for [%s] is not employed by active platform\n" \
1395 % (self
.MetaFile
, Arch
))
1398 self
.SourceDir
= self
.MetaFile
.SubDir
1399 self
.SourceOverrideDir
= None
1400 # use overrided path defined in DSC file
1401 if self
.MetaFile
.Key
in GlobalData
.gOverrideDir
:
1402 self
.SourceOverrideDir
= GlobalData
.gOverrideDir
[self
.MetaFile
.Key
]
1404 self
.ToolChain
= Toolchain
1405 self
.BuildTarget
= Target
1407 self
.ToolChainFamily
= self
.PlatformInfo
.ToolChainFamily
1408 self
.BuildRuleFamily
= self
.PlatformInfo
.BuildRuleFamily
1410 self
.IsMakeFileCreated
= False
1411 self
.IsCodeFileCreated
= False
1413 self
.BuildDatabase
= self
.Workspace
.BuildDatabase
1418 self
._Version
= None
1419 self
._ModuleType
= None
1420 self
._ComponentType
= None
1421 self
._PcdIsDriver
= None
1422 self
._AutoGenVersion
= None
1423 self
._LibraryFlag
= None
1424 self
._CustomMakefile
= None
1427 self
._BuildDir
= None
1428 self
._OutputDir
= None
1429 self
._DebugDir
= None
1430 self
._MakeFileDir
= None
1432 self
._IncludePathList
= None
1433 self
._AutoGenFileList
= None
1434 self
._UnicodeFileList
= None
1435 self
._SourceFileList
= None
1436 self
._ObjectFileList
= None
1437 self
._BinaryFileList
= None
1439 self
._DependentPackageList
= None
1440 self
._DependentLibraryList
= None
1441 self
._LibraryAutoGenList
= None
1442 self
._DerivedPackageList
= None
1443 self
._ModulePcdList
= None
1444 self
._LibraryPcdList
= None
1445 self
._GuidList
= None
1446 self
._ProtocolList
= None
1447 self
._PpiList
= None
1448 self
._DepexList
= None
1449 self
._DepexExpressionList
= None
1450 self
._BuildOption
= None
1451 self
._BuildTargets
= None
1452 self
._IntroBuildTargetList
= None
1453 self
._FinalBuildTargetList
= None
1454 self
._FileTypes
= None
1455 self
._BuildRules
= None
1460 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
1462 # Macros could be used in build_rule.txt (also Makefile)
1463 def _GetMacros(self
):
1464 if self
._Macro
== None:
1465 self
._Macro
= sdict()
1466 self
._Macro
["WORKSPACE" ] = self
.WorkspaceDir
1467 self
._Macro
["MODULE_NAME" ] = self
.Name
1468 self
._Macro
["MODULE_GUID" ] = self
.Guid
1469 self
._Macro
["MODULE_VERSION" ] = self
.Version
1470 self
._Macro
["MODULE_TYPE" ] = self
.ModuleType
1471 self
._Macro
["MODULE_FILE" ] = str(self
.MetaFile
)
1472 self
._Macro
["MODULE_FILE_BASE_NAME" ] = self
.MetaFile
.BaseName
1473 self
._Macro
["MODULE_RELATIVE_DIR" ] = self
.SourceDir
1474 self
._Macro
["MODULE_DIR" ] = self
.SourceDir
1476 self
._Macro
["BASE_NAME" ] = self
.Name
1478 self
._Macro
["ARCH" ] = self
.Arch
1479 self
._Macro
["TOOLCHAIN" ] = self
.ToolChain
1480 self
._Macro
["TOOLCHAIN_TAG" ] = self
.ToolChain
1481 self
._Macro
["TARGET" ] = self
.BuildTarget
1483 self
._Macro
["BUILD_DIR" ] = self
.PlatformInfo
.BuildDir
1484 self
._Macro
["BIN_DIR" ] = os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)
1485 self
._Macro
["LIB_DIR" ] = os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)
1486 self
._Macro
["MODULE_BUILD_DIR" ] = self
.BuildDir
1487 self
._Macro
["OUTPUT_DIR" ] = self
.OutputDir
1488 self
._Macro
["DEBUG_DIR" ] = self
.DebugDir
1491 ## Return the module build data object
1492 def _GetModule(self
):
1493 if self
._Module
== None:
1494 self
._Module
= self
.Workspace
.BuildDatabase
[self
.MetaFile
, self
.Arch
]
1497 ## Return the module name
1498 def _GetBaseName(self
):
1499 return self
.Module
.BaseName
1501 ## Return the module SourceOverridePath
1502 def _GetSourceOverridePath(self
):
1503 return self
.Module
.SourceOverridePath
1505 ## Return the module meta-file GUID
1507 return self
.Module
.Guid
1509 ## Return the module version
1510 def _GetVersion(self
):
1511 return self
.Module
.Version
1513 ## Return the module type
1514 def _GetModuleType(self
):
1515 return self
.Module
.ModuleType
1517 ## Return the component type (for R8.x style of module)
1518 def _GetComponentType(self
):
1519 return self
.Module
.ComponentType
1521 ## Return the build type
1522 def _GetBuildType(self
):
1523 return self
.Module
.BuildType
1525 ## Return the PCD_IS_DRIVER setting
1526 def _GetPcdIsDriver(self
):
1527 return self
.Module
.PcdIsDriver
1529 ## Return the autogen version, i.e. module meta-file version
1530 def _GetAutoGenVersion(self
):
1531 return self
.Module
.AutoGenVersion
1533 ## Check if the module is library or not
1534 def _IsLibrary(self
):
1535 if self
._LibraryFlag
== None:
1536 if self
.Module
.LibraryClass
!= None and self
.Module
.LibraryClass
!= []:
1537 self
._LibraryFlag
= True
1539 self
._LibraryFlag
= False
1540 return self
._LibraryFlag
1542 ## Return the directory to store intermediate files of the module
1543 def _GetBuildDir(self
):
1544 if self
._BuildDir
== None:
1545 self
._BuildDir
= path
.join(
1546 self
.PlatformInfo
.BuildDir
,
1549 self
.MetaFile
.BaseName
1551 CreateDirectory(self
._BuildDir
)
1552 return self
._BuildDir
1554 ## Return the directory to store the intermediate object files of the mdoule
1555 def _GetOutputDir(self
):
1556 if self
._OutputDir
== None:
1557 self
._OutputDir
= path
.join(self
.BuildDir
, "OUTPUT")
1558 CreateDirectory(self
._OutputDir
)
1559 return self
._OutputDir
1561 ## Return the directory to store auto-gened source files of the mdoule
1562 def _GetDebugDir(self
):
1563 if self
._DebugDir
== None:
1564 self
._DebugDir
= path
.join(self
.BuildDir
, "DEBUG")
1565 CreateDirectory(self
._DebugDir
)
1566 return self
._DebugDir
1568 ## Return the path of custom file
1569 def _GetCustomMakefile(self
):
1570 if self
._CustomMakefile
== None:
1571 self
._CustomMakefile
= {}
1572 for Type
in self
.Module
.CustomMakefile
:
1573 if Type
in gMakeTypeMap
:
1574 MakeType
= gMakeTypeMap
[Type
]
1577 if self
.SourceOverrideDir
!= None:
1578 File
= os
.path
.join(self
.SourceOverrideDir
, self
.Module
.CustomMakefile
[Type
])
1579 if not os
.path
.exists(File
):
1580 File
= os
.path
.join(self
.SourceDir
, self
.Module
.CustomMakefile
[Type
])
1582 File
= os
.path
.join(self
.SourceDir
, self
.Module
.CustomMakefile
[Type
])
1583 self
._CustomMakefile
[MakeType
] = File
1584 return self
._CustomMakefile
1586 ## Return the directory of the makefile
1588 # @retval string The directory string of module's makefile
1590 def _GetMakeFileDir(self
):
1591 return self
.BuildDir
1593 ## Return build command string
1595 # @retval string Build command string
1597 def _GetBuildCommand(self
):
1598 return self
.PlatformInfo
.BuildCommand
1600 ## Get object list of all packages the module and its dependent libraries belong to
1602 # @retval list The list of package object
1604 def _GetDerivedPackageList(self
):
1606 for M
in [self
.Module
] + self
.DependentLibraryList
:
1607 for Package
in M
.Packages
:
1608 if Package
in PackageList
:
1610 PackageList
.append(Package
)
1613 ## Merge dependency expression
1615 # @retval list The token list of the dependency expression after parsed
1617 def _GetDepexTokenList(self
):
1618 if self
._DepexList
== None:
1619 self
._DepexList
= {}
1620 if self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
1621 return self
._DepexList
1623 self
._DepexList
[self
.ModuleType
] = []
1625 for ModuleType
in self
._DepexList
:
1626 DepexList
= self
._DepexList
[ModuleType
]
1628 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
1630 for M
in [self
.Module
] + self
.DependentLibraryList
:
1632 for D
in M
.Depex
[self
.Arch
, ModuleType
]:
1634 DepexList
.append('AND')
1635 DepexList
.append('(')
1637 if DepexList
[-1] == 'END': # no need of a END at this time
1639 DepexList
.append(')')
1642 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexList
))
1643 if 'BEFORE' in DepexList
or 'AFTER' in DepexList
:
1645 if len(DepexList
) > 0:
1646 EdkLogger
.verbose('')
1647 return self
._DepexList
1649 ## Merge dependency expression
1651 # @retval list The token list of the dependency expression after parsed
1653 def _GetDepexExpressionTokenList(self
):
1654 if self
._DepexExpressionList
== None:
1655 self
._DepexExpressionList
= {}
1656 if self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
1657 return self
._DepexExpressionList
1659 self
._DepexExpressionList
[self
.ModuleType
] = ''
1661 for ModuleType
in self
._DepexExpressionList
:
1662 DepexExpressionList
= self
._DepexExpressionList
[ModuleType
]
1664 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
1666 for M
in [self
.Module
] + self
.DependentLibraryList
:
1668 for D
in M
.DepexExpression
[self
.Arch
, ModuleType
]:
1669 if DepexExpressionList
!= '':
1670 DepexExpressionList
+= ' AND '
1671 DepexExpressionList
+= '('
1672 DepexExpressionList
+= D
1673 DepexExpressionList
= DepexExpressionList
.rstrip('END').strip()
1674 DepexExpressionList
+= ')'
1677 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexExpressionList
))
1678 if 'BEFORE' in DepexExpressionList
or 'AFTER' in DepexExpressionList
:
1680 if len(DepexExpressionList
) > 0:
1681 EdkLogger
.verbose('')
1682 self
._DepexExpressionList
[ModuleType
] = DepexExpressionList
1683 return self
._DepexExpressionList
1685 ## Return the list of specification version required for the module
1687 # @retval list The list of specification defined in module file
1689 def _GetSpecification(self
):
1690 return self
.Module
.Specification
1692 ## Tool option for the module build
1694 # @param PlatformInfo The object of PlatformBuildInfo
1695 # @retval dict The dict containing valid options
1697 def _GetModuleBuildOption(self
):
1698 if self
._BuildOption
== None:
1699 self
._BuildOption
= self
.PlatformInfo
.ApplyBuildOption(self
.Module
)
1700 return self
._BuildOption
1702 ## Return a list of files which can be built from source
1704 # What kind of files can be built is determined by build rules in
1705 # $(WORKSPACE)/Conf/build_rule.txt and toolchain family.
1707 def _GetSourceFileList(self
):
1708 if self
._SourceFileList
== None:
1709 self
._SourceFileList
= []
1710 for F
in self
.Module
.Sources
:
1712 if F
.TagName
!= "" and F
.TagName
!= self
.ToolChain
:
1713 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "The toolchain [%s] for processing file [%s] is found, "
1714 "but [%s] is needed" % (F
.TagName
, str(F
), self
.ToolChain
))
1716 # match tool chain family
1717 if F
.ToolChainFamily
!= "" and F
.ToolChainFamily
!= self
.ToolChainFamily
:
1720 "The file [%s] must be built by tools of [%s], " \
1721 "but current toolchain family is [%s]" \
1722 % (str(F
), F
.ToolChainFamily
, self
.ToolChainFamily
))
1725 # add the file path into search path list for file including
1726 if F
.Dir
not in self
.IncludePathList
and self
.AutoGenVersion
>= 0x00010005:
1727 self
.IncludePathList
.insert(0, F
.Dir
)
1728 self
._SourceFileList
.append(F
)
1729 self
._ApplyBuildRule
(F
, TAB_UNKNOWN_FILE
)
1730 return self
._SourceFileList
1732 ## Return the list of unicode files
1733 def _GetUnicodeFileList(self
):
1734 if self
._UnicodeFileList
== None:
1735 if TAB_UNICODE_FILE
in self
.FileTypes
:
1736 self
._UnicodeFileList
= self
.FileTypes
[TAB_UNICODE_FILE
]
1738 self
._UnicodeFileList
= []
1739 return self
._UnicodeFileList
1741 ## Return a list of files which can be built from binary
1743 # "Build" binary files are just to copy them to build directory.
1745 # @retval list The list of files which can be built later
1747 def _GetBinaryFiles(self
):
1748 if self
._BinaryFileList
== None:
1749 self
._BinaryFileList
= []
1750 for F
in self
.Module
.Binaries
:
1751 if F
.Target
not in ['COMMON', '*'] and F
.Target
!= self
.BuildTarget
:
1753 self
._BinaryFileList
.append(F
)
1754 self
._ApplyBuildRule
(F
, F
.Type
)
1755 return self
._BinaryFileList
1757 def _GetBuildRules(self
):
1758 if self
._BuildRules
== None:
1760 BuildRuleDatabase
= self
.PlatformInfo
.BuildRule
1761 for Type
in BuildRuleDatabase
.FileTypeList
:
1762 #first try getting build rule by BuildRuleFamily
1763 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.BuildRuleFamily
]
1765 # build type is always module type, but ...
1766 if self
.ModuleType
!= self
.BuildType
:
1767 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.BuildRuleFamily
]
1768 #second try getting build rule by ToolChainFamily
1770 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.ToolChainFamily
]
1772 # build type is always module type, but ...
1773 if self
.ModuleType
!= self
.BuildType
:
1774 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.ToolChainFamily
]
1777 RuleObject
= RuleObject
.Instantiate(self
.Macros
)
1778 BuildRules
[Type
] = RuleObject
1779 for Ext
in RuleObject
.SourceFileExtList
:
1780 BuildRules
[Ext
] = RuleObject
1781 self
._BuildRules
= BuildRules
1782 return self
._BuildRules
1784 def _ApplyBuildRule(self
, File
, FileType
):
1785 if self
._BuildTargets
== None:
1786 self
._IntroBuildTargetList
= set()
1787 self
._FinalBuildTargetList
= set()
1788 self
._BuildTargets
= {}
1789 self
._FileTypes
= {}
1795 while Index
< len(SourceList
):
1796 Source
= SourceList
[Index
]
1800 CreateDirectory(Source
.Dir
)
1802 if File
.IsBinary
and File
== Source
and self
._BinaryFileList
!= None and File
in self
._BinaryFileList
:
1803 RuleObject
= self
.BuildRules
[TAB_DEFAULT_BINARY_FILE
]
1804 elif FileType
in self
.BuildRules
:
1805 RuleObject
= self
.BuildRules
[FileType
]
1806 elif Source
.Ext
in self
.BuildRules
:
1807 RuleObject
= self
.BuildRules
[Source
.Ext
]
1809 # stop at no more rules
1811 self
._FinalBuildTargetList
.add(LastTarget
)
1814 FileType
= RuleObject
.SourceFileType
1815 if FileType
not in self
._FileTypes
:
1816 self
._FileTypes
[FileType
] = set()
1817 self
._FileTypes
[FileType
].add(Source
)
1819 # stop at STATIC_LIBRARY for library
1820 if self
.IsLibrary
and FileType
== TAB_STATIC_LIBRARY
:
1822 self
._FinalBuildTargetList
.add(LastTarget
)
1825 Target
= RuleObject
.Apply(Source
)
1828 self
._FinalBuildTargetList
.add(LastTarget
)
1830 elif not Target
.Outputs
:
1831 # Only do build for target with outputs
1832 self
._FinalBuildTargetList
.add(Target
)
1834 if FileType
not in self
._BuildTargets
:
1835 self
._BuildTargets
[FileType
] = set()
1836 self
._BuildTargets
[FileType
].add(Target
)
1838 if not Source
.IsBinary
and Source
== File
:
1839 self
._IntroBuildTargetList
.add(Target
)
1841 # to avoid cyclic rule
1842 if FileType
in RuleChain
:
1845 RuleChain
.append(FileType
)
1846 SourceList
.extend(Target
.Outputs
)
1848 FileType
= TAB_UNKNOWN_FILE
1850 def _GetTargets(self
):
1851 if self
._BuildTargets
== None:
1852 self
._IntroBuildTargetList
= set()
1853 self
._FinalBuildTargetList
= set()
1854 self
._BuildTargets
= {}
1855 self
._FileTypes
= {}
1857 #TRICK: call _GetSourceFileList to apply build rule for binary files
1858 if self
.SourceFileList
:
1861 #TRICK: call _GetBinaryFileList to apply build rule for binary files
1862 if self
.BinaryFileList
:
1865 return self
._BuildTargets
1867 def _GetIntroTargetList(self
):
1869 return self
._IntroBuildTargetList
1871 def _GetFinalTargetList(self
):
1873 return self
._FinalBuildTargetList
1875 def _GetFileTypes(self
):
1877 return self
._FileTypes
1879 ## Get the list of package object the module depends on
1881 # @retval list The package object list
1883 def _GetDependentPackageList(self
):
1884 return self
.Module
.Packages
1886 ## Return the list of auto-generated code file
1888 # @retval list The list of auto-generated file
1890 def _GetAutoGenFileList(self
):
1891 UniStringAutoGenC
= True
1892 UniStringBinBuffer
= None
1893 if self
.BuildType
== 'UEFI_HII':
1894 UniStringBinBuffer
= StringIO()
1895 UniStringAutoGenC
= False
1896 if self
._AutoGenFileList
== None:
1897 self
._AutoGenFileList
= {}
1898 AutoGenC
= TemplateString()
1899 AutoGenH
= TemplateString()
1900 StringH
= TemplateString()
1901 GenC
.CreateCode(self
, AutoGenC
, AutoGenH
, StringH
, UniStringAutoGenC
, UniStringBinBuffer
)
1902 if str(AutoGenC
) != "" and TAB_C_CODE_FILE
in self
.FileTypes
:
1903 AutoFile
= PathClass(gAutoGenCodeFileName
, self
.DebugDir
)
1904 self
._AutoGenFileList
[AutoFile
] = str(AutoGenC
)
1905 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
1906 if str(AutoGenH
) != "":
1907 AutoFile
= PathClass(gAutoGenHeaderFileName
, self
.DebugDir
)
1908 self
._AutoGenFileList
[AutoFile
] = str(AutoGenH
)
1909 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
1910 if str(StringH
) != "":
1911 AutoFile
= PathClass(gAutoGenStringFileName
% {"module_name":self
.Name
}, self
.DebugDir
)
1912 self
._AutoGenFileList
[AutoFile
] = str(StringH
)
1913 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
1914 if UniStringBinBuffer
!= None and UniStringBinBuffer
.getvalue() != "":
1915 AutoFile
= PathClass(gAutoGenStringFormFileName
% {"module_name":self
.Name
}, self
.OutputDir
)
1916 self
._AutoGenFileList
[AutoFile
] = UniStringBinBuffer
.getvalue()
1917 AutoFile
.IsBinary
= True
1918 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
1919 if UniStringBinBuffer
!= None:
1920 UniStringBinBuffer
.close()
1921 return self
._AutoGenFileList
1923 ## Return the list of library modules explicitly or implicityly used by this module
1924 def _GetLibraryList(self
):
1925 if self
._DependentLibraryList
== None:
1926 # only merge library classes and PCD for non-library module
1928 self
._DependentLibraryList
= []
1930 if self
.AutoGenVersion
< 0x00010005:
1931 self
._DependentLibraryList
= self
.PlatformInfo
.ResolveLibraryReference(self
.Module
)
1933 self
._DependentLibraryList
= self
.PlatformInfo
.ApplyLibraryInstance(self
.Module
)
1934 return self
._DependentLibraryList
1936 ## Get the list of PCDs from current module
1938 # @retval list The list of PCD
1940 def _GetModulePcdList(self
):
1941 if self
._ModulePcdList
== None:
1942 # apply PCD settings from platform
1943 self
._ModulePcdList
= self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, self
.Module
.Pcds
)
1944 return self
._ModulePcdList
1946 ## Get the list of PCDs from dependent libraries
1948 # @retval list The list of PCD
1950 def _GetLibraryPcdList(self
):
1951 if self
._LibraryPcdList
== None:
1953 if not self
.IsLibrary
:
1954 # get PCDs from dependent libraries
1955 for Library
in self
.DependentLibraryList
:
1956 for Key
in Library
.Pcds
:
1957 # skip duplicated PCDs
1958 if Key
in self
.Module
.Pcds
or Key
in Pcds
:
1960 Pcds
[Key
] = copy
.copy(Library
.Pcds
[Key
])
1961 # apply PCD settings from platform
1962 self
._LibraryPcdList
= self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, Pcds
)
1964 self
._LibraryPcdList
= []
1965 return self
._LibraryPcdList
1967 ## Get the GUID value mapping
1969 # @retval dict The mapping between GUID cname and its value
1971 def _GetGuidList(self
):
1972 if self
._GuidList
== None:
1973 self
._GuidList
= self
.Module
.Guids
1974 for Library
in self
.DependentLibraryList
:
1975 self
._GuidList
.update(Library
.Guids
)
1976 return self
._GuidList
1978 ## Get the protocol value mapping
1980 # @retval dict The mapping between protocol cname and its value
1982 def _GetProtocolList(self
):
1983 if self
._ProtocolList
== None:
1984 self
._ProtocolList
= self
.Module
.Protocols
1985 for Library
in self
.DependentLibraryList
:
1986 self
._ProtocolList
.update(Library
.Protocols
)
1987 return self
._ProtocolList
1989 ## Get the PPI value mapping
1991 # @retval dict The mapping between PPI cname and its value
1993 def _GetPpiList(self
):
1994 if self
._PpiList
== None:
1995 self
._PpiList
= self
.Module
.Ppis
1996 for Library
in self
.DependentLibraryList
:
1997 self
._PpiList
.update(Library
.Ppis
)
1998 return self
._PpiList
2000 ## Get the list of include search path
2002 # @retval list The list path
2004 def _GetIncludePathList(self
):
2005 if self
._IncludePathList
== None:
2006 self
._IncludePathList
= []
2007 if self
.AutoGenVersion
< 0x00010005:
2008 for Inc
in self
.Module
.Includes
:
2009 if Inc
not in self
._IncludePathList
:
2010 self
._IncludePathList
.append(Inc
)
2012 Inc
= path
.join(Inc
, self
.Arch
.capitalize())
2013 if os
.path
.exists(Inc
) and Inc
not in self
._IncludePathList
:
2014 self
._IncludePathList
.append(Inc
)
2015 # r8 module needs to put DEBUG_DIR at the end of search path and not to use SOURCE_DIR all the time
2016 self
._IncludePathList
.append(self
.DebugDir
)
2018 self
._IncludePathList
.append(self
.MetaFile
.Dir
)
2019 self
._IncludePathList
.append(self
.DebugDir
)
2021 for Package
in self
.Module
.Packages
:
2022 PackageDir
= path
.join(self
.WorkspaceDir
, Package
.MetaFile
.Dir
)
2023 if PackageDir
not in self
._IncludePathList
:
2024 self
._IncludePathList
.append(PackageDir
)
2025 for Inc
in Package
.Includes
:
2026 if Inc
not in self
._IncludePathList
:
2027 self
._IncludePathList
.append(str(Inc
))
2028 return self
._IncludePathList
2030 ## Create makefile for the module and its dependent libraries
2032 # @param CreateLibraryMakeFile Flag indicating if or not the makefiles of
2033 # dependent libraries will be created
2035 def CreateMakeFile(self
, CreateLibraryMakeFile
=True):
2036 if self
.IsMakeFileCreated
:
2039 if not self
.IsLibrary
and CreateLibraryMakeFile
:
2040 for LibraryAutoGen
in self
.LibraryAutoGenList
:
2041 LibraryAutoGen
.CreateMakeFile()
2043 if len(self
.CustomMakefile
) == 0:
2044 Makefile
= GenMake
.ModuleMakefile(self
)
2046 Makefile
= GenMake
.CustomMakefile(self
)
2047 if Makefile
.Generate():
2048 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated makefile for module %s [%s]" %
2049 (self
.Name
, self
.Arch
))
2051 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of makefile for module %s [%s]" %
2052 (self
.Name
, self
.Arch
))
2054 self
.IsMakeFileCreated
= True
2056 ## Create autogen code for the module and its dependent libraries
2058 # @param CreateLibraryCodeFile Flag indicating if or not the code of
2059 # dependent libraries will be created
2061 def CreateCodeFile(self
, CreateLibraryCodeFile
=True):
2062 if self
.IsCodeFileCreated
:
2065 if not self
.IsLibrary
and CreateLibraryCodeFile
:
2066 for LibraryAutoGen
in self
.LibraryAutoGenList
:
2067 LibraryAutoGen
.CreateCodeFile()
2070 IgoredAutoGenList
= []
2072 for File
in self
.AutoGenFileList
:
2073 if GenC
.Generate(File
.Path
, self
.AutoGenFileList
[File
], File
.IsBinary
):
2074 #Ignore R8 AutoGen.c
2075 if self
.AutoGenVersion
< 0x00010005 and File
.Name
== 'AutoGen.c':
2078 AutoGenList
.append(str(File
))
2080 IgoredAutoGenList
.append(str(File
))
2082 # Skip the following code for EDK I inf
2083 if self
.AutoGenVersion
< 0x00010005:
2086 for ModuleType
in self
.DepexList
:
2087 # Ignore empty [depex] section or [depex] section for "USER_DEFINED" module
2088 if len(self
.DepexList
[ModuleType
]) == 0 or ModuleType
== "USER_DEFINED":
2091 Dpx
= GenDepex
.DependencyExpression(self
.DepexList
[ModuleType
], ModuleType
, True)
2092 DpxFile
= gAutoGenDepexFileName
% {"module_name" : self
.Name
}
2094 if Dpx
.Generate(path
.join(self
.OutputDir
, DpxFile
)):
2095 AutoGenList
.append(str(DpxFile
))
2097 IgoredAutoGenList
.append(str(DpxFile
))
2099 if IgoredAutoGenList
== []:
2100 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] files for module %s [%s]" %
2101 (" ".join(AutoGenList
), self
.Name
, self
.Arch
))
2102 elif AutoGenList
== []:
2103 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of [%s] files for module %s [%s]" %
2104 (" ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
2106 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] (skipped %s) files for module %s [%s]" %
2107 (" ".join(AutoGenList
), " ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
2109 self
.IsCodeFileCreated
= True
2112 ## Summarize the ModuleAutoGen objects of all libraries used by this module
2113 def _GetLibraryAutoGenList(self
):
2114 if self
._LibraryAutoGenList
== None:
2115 self
._LibraryAutoGenList
= []
2116 for Library
in self
.DependentLibraryList
:
2123 self
.PlatformInfo
.MetaFile
2125 if La
not in self
._LibraryAutoGenList
:
2126 self
._LibraryAutoGenList
.append(La
)
2127 for Lib
in La
.CodaTargetList
:
2128 self
._ApplyBuildRule
(Lib
.Target
, TAB_UNKNOWN_FILE
)
2129 return self
._LibraryAutoGenList
2131 ## Return build command string
2133 # @retval string Build command string
2135 def _GetBuildCommand(self
):
2136 return self
.PlatformInfo
.BuildCommand
2139 Module
= property(_GetModule
)
2140 Name
= property(_GetBaseName
)
2141 Guid
= property(_GetGuid
)
2142 Version
= property(_GetVersion
)
2143 ModuleType
= property(_GetModuleType
)
2144 ComponentType
= property(_GetComponentType
)
2145 BuildType
= property(_GetBuildType
)
2146 PcdIsDriver
= property(_GetPcdIsDriver
)
2147 AutoGenVersion
= property(_GetAutoGenVersion
)
2148 Macros
= property(_GetMacros
)
2149 Specification
= property(_GetSpecification
)
2151 IsLibrary
= property(_IsLibrary
)
2153 BuildDir
= property(_GetBuildDir
)
2154 OutputDir
= property(_GetOutputDir
)
2155 DebugDir
= property(_GetDebugDir
)
2156 MakeFileDir
= property(_GetMakeFileDir
)
2157 CustomMakefile
= property(_GetCustomMakefile
)
2159 IncludePathList
= property(_GetIncludePathList
)
2160 AutoGenFileList
= property(_GetAutoGenFileList
)
2161 UnicodeFileList
= property(_GetUnicodeFileList
)
2162 SourceFileList
= property(_GetSourceFileList
)
2163 BinaryFileList
= property(_GetBinaryFiles
) # FileType : [File List]
2164 Targets
= property(_GetTargets
)
2165 IntroTargetList
= property(_GetIntroTargetList
)
2166 CodaTargetList
= property(_GetFinalTargetList
)
2167 FileTypes
= property(_GetFileTypes
)
2168 BuildRules
= property(_GetBuildRules
)
2170 DependentPackageList
= property(_GetDependentPackageList
)
2171 DependentLibraryList
= property(_GetLibraryList
)
2172 LibraryAutoGenList
= property(_GetLibraryAutoGenList
)
2173 DerivedPackageList
= property(_GetDerivedPackageList
)
2175 ModulePcdList
= property(_GetModulePcdList
)
2176 LibraryPcdList
= property(_GetLibraryPcdList
)
2177 GuidList
= property(_GetGuidList
)
2178 ProtocolList
= property(_GetProtocolList
)
2179 PpiList
= property(_GetPpiList
)
2180 DepexList
= property(_GetDepexTokenList
)
2181 DepexExpressionList
= property(_GetDepexExpressionTokenList
)
2182 BuildOption
= property(_GetModuleBuildOption
)
2183 BuildCommand
= property(_GetBuildCommand
)
2185 # This acts like the main() function for the script, unless it is 'import'ed into another script.
2186 if __name__
== '__main__':