]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/AutoGen/AutoGen.py
Sync EDKII BaseTools to BaseTools project r2042.
[mirror_edk2.git] / BaseTools / Source / Python / AutoGen / AutoGen.py
1 ## @file
2 # Generate AutoGen.h, AutoGen.c and *.depex files
3 #
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
9 #
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.
12 #
13
14 ## Import Modules
15 #
16 import os
17 import re
18 import os.path as path
19 import copy
20
21 import GenC
22 import GenMake
23 import GenDepex
24 from StringIO import StringIO
25
26 from StrGather import *
27 from BuildEngine import BuildRule
28
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
38
39 ## Regular expression for splitting Dependency Expression stirng into tokens
40 gDepexTokenPattern = re.compile("(\(|\)|\w+| \S+\.inf)")
41
42 ## Mapping Makefile type
43 gMakeTypeMap = {"MSFT":"nmake", "GCC":"gmake"}
44
45
46 ## Build rule configuration file
47 gBuildRuleFile = 'Conf/build_rule.txt'
48
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"
55
56 ## Base class for AutoGen
57 #
58 # This class just implements the cache mechanism of AutoGen objects.
59 #
60 class AutoGen(object):
61 # database to maintain the objects of xxxAutoGen
62 _CACHE_ = {} # (BuildTarget, ToolChain) : {ARCH : {platform file: AutoGen object}}}
63
64 ## Factory method
65 #
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
75 #
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):
84 return None
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
90 else:
91 AutoGenObject = Class._CACHE_[Key][Arch][MetaFile]
92
93 return AutoGenObject
94
95 ## hash() operator
96 #
97 # The file path of platform file will be used to represent hash value of this object
98 #
99 # @retval int Hash value of the file path of platform file
100 #
101 def __hash__(self):
102 return hash(self.MetaFile)
103
104 ## str() operator
105 #
106 # The file path of platform file will be used to represent this object
107 #
108 # @retval string String of platform file path
109 #
110 def __str__(self):
111 return str(self.MetaFile)
112
113 ## "==" operator
114 def __eq__(self, Other):
115 return Other and self.MetaFile == Other
116
117 ## Workspace AutoGen class
118 #
119 # This class is used mainly to control the whole platform build for different
120 # architecture. This class will generate top level makefile.
121 #
122 class WorkspaceAutoGen(AutoGen):
123 ## Real constructor of WorkspaceAutoGen
124 #
125 # This method behaves the same as __init__ except that it needs explict invoke
126 # (in super class's __new__ method)
127 #
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
140 #
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
149 self.SkuId = SkuId
150 self.UniFlag = UniFlag
151
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 = []
159
160 # there's many relative directory operations, so ...
161 os.chdir(self.WorkspaceDir)
162
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)
166 Fdf.ParseFile()
167 PcdSet = Fdf.Profile.PcdDict
168 ModuleList = Fdf.Profile.InfList
169 self.FdfProfile = Fdf.Profile
170 else:
171 PcdSet = {}
172 ModuleList = []
173 self.FdfProfile = None
174
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])
181
182 Pa = PlatformAutoGen(self, self.MetaFile, Target, Toolchain, Arch)
183 #
184 # Explicitly collect platform's dynamic PCDs
185 #
186 Pa.CollectPlatformDynamicPcds()
187 self.AutoGenObjectList.append(Pa)
188
189 self._BuildDir = None
190 self._FvDir = None
191 self._MakeFileDir = None
192 self._BuildCommand = None
193
194 return True
195
196 def __repr__(self):
197 return "%s [%s]" % (self.MetaFile, ", ".join(self.ArchList))
198
199 ## Return the directory to store FV files
200 def _GetFvDir(self):
201 if self._FvDir == None:
202 self._FvDir = path.join(self.BuildDir, 'FV')
203 return self._FvDir
204
205 ## Return the directory to store all intermediate and final files built
206 def _GetBuildDir(self):
207 return self.AutoGenObjectList[0].BuildDir
208
209 ## Return the build output directory platform specifies
210 def _GetOutputDir(self):
211 return self.Platform.OutputDirectory
212
213 ## Return platform name
214 def _GetName(self):
215 return self.Platform.PlatformName
216
217 ## Return meta-file GUID
218 def _GetGuid(self):
219 return self.Platform.Guid
220
221 ## Return platform version
222 def _GetVersion(self):
223 return self.Platform.Version
224
225 ## Return paths of tools
226 def _GetToolDefinition(self):
227 return self.AutoGenObjectList[0].ToolDefinition
228
229 ## Return directory of platform makefile
230 #
231 # @retval string Makefile directory
232 #
233 def _GetMakeFileDir(self):
234 if self._MakeFileDir == None:
235 self._MakeFileDir = self.BuildDir
236 return self._MakeFileDir
237
238 ## Return build command string
239 #
240 # @retval string Build command string
241 #
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
247
248 ## Create makefile for the platform and modules in it
249 #
250 # @param CreateDepsMakeFile Flag indicating if the makefile for
251 # modules will be created as well
252 #
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))
259 else:
260 EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of makefile for platform [%s] %s\n" %
261 (self.MetaFile, self.ArchList))
262
263 if CreateDepsMakeFile:
264 for Pa in self.AutoGenObjectList:
265 Pa.CreateMakeFile(CreateDepsMakeFile)
266
267 ## Create autogen code for platform and modules
268 #
269 # Since there's no autogen code for platform, this method will do nothing
270 # if CreateModuleCodeFile is set to False.
271 #
272 # @param CreateDepsCodeFile Flag indicating if creating module's
273 # autogen code file or not
274 #
275 def CreateCodeFile(self, CreateDepsCodeFile=False):
276 if not CreateDepsCodeFile:
277 return
278 for Pa in self.AutoGenObjectList:
279 Pa.CreateCodeFile(CreateDepsCodeFile)
280
281 Name = property(_GetName)
282 Guid = property(_GetGuid)
283 Version = property(_GetVersion)
284 OutputDir = property(_GetOutputDir)
285
286 ToolDefinition = property(_GetToolDefinition) # toolcode : tool path
287
288 BuildDir = property(_GetBuildDir)
289 FvDir = property(_GetFvDir)
290 MakeFileDir = property(_GetMakeFileDir)
291 BuildCommand = property(_GetBuildCommand)
292
293 ## AutoGen class for platform
294 #
295 # PlatformAutoGen class will process the original information in platform
296 # file in order to generate makefile for platform.
297 #
298 class PlatformAutoGen(AutoGen):
299 #
300 # Used to store all PCDs for both PEI and DXE phase, in order to generate
301 # correct PCD database
302 #
303 _DynaPcdList_ = []
304 _NonDynaPcdList_ = []
305
306 ## The real constructor of PlatformAutoGen
307 #
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
311 #
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
317 #
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)
321
322 self.MetaFile = PlatformFile
323 self.Workspace = Workspace
324 self.WorkspaceDir = Workspace.WorkspaceDir
325 self.ToolChain = Toolchain
326 self.BuildTarget = Target
327 self.Arch = Arch
328 self.SourceDir = PlatformFile.SubDir
329 self.SourceOverrideDir = None
330 self.FdTargetList = self.Workspace.FdTargetList
331 self.FvTargetList = self.Workspace.FvTargetList
332 self.AllPcdList = []
333
334 # flag indicating if the makefile/C-code file has been created or not
335 self.IsMakeFileCreated = False
336 self.IsCodeFileCreated = False
337
338 self._Platform = None
339 self._Name = None
340 self._Guid = None
341 self._Version = None
342
343 self._BuildRule = None
344 self._SourceDir = None
345 self._BuildDir = None
346 self._OutputDir = None
347 self._FvDir = None
348 self._MakeFileDir = None
349 self._FdfFile = None
350
351 self._PcdTokenNumber = None # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
352 self._DynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
353 self._NonDynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
354
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
366
367 # get the original module/package/platform objects
368 self.BuildDatabase = Workspace.BuildDatabase
369 return True
370
371 def __repr__(self):
372 return "%s [%s]" % (self.MetaFile, self.Arch)
373
374 ## Create autogen code for platform and modules
375 #
376 # Since there's no autogen code for platform, this method will do nothing
377 # if CreateModuleCodeFile is set to False.
378 #
379 # @param CreateModuleCodeFile Flag indicating if creating module's
380 # autogen code file or not
381 #
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:
385 return
386
387 for Ma in self.ModuleAutoGenList:
388 Ma.CreateCodeFile(True)
389
390 # don't do this twice
391 self.IsCodeFileCreated = True
392
393 ## Create makefile for the platform and mdoules in it
394 #
395 # @param CreateModuleMakeFile Flag indicating if the makefile for
396 # modules will be created as well
397 #
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)
404
405 # no need to create makefile for the platform more than once
406 if self.IsMakeFileCreated:
407 return
408
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))
414 else:
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
418
419 ## Collect dynamic PCDs
420 #
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.
423 #
424 def CollectPlatformDynamicPcds(self):
425 # for gathering error information
426 NoDatumTypePcdList = set()
427
428 self._GuidValue = {}
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)
432
433 self.Platform.Modules[F].M = M
434
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))
439
440 if PcdFromModule.Type in GenC.gDynamicPcd or PcdFromModule.Type in GenC.gDynamicExPcd:
441 #
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
446 #
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)
457
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",
462 File=self.MetaFile,
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
468
469 #
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
474 #
475 # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.
476 #
477 UnicodePcdArray = []
478 HiiPcdArray = []
479 OtherPcdArray = []
480 VpdFile = VpdInfoFile.VpdInfoFile()
481 NeedProcessVpdMapFile = False
482
483 if (self.Workspace.ArchList[-1] == self.Arch):
484 for Pcd in self._DynamicPcdList:
485
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()
489
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)
497 else:
498 OtherPcdArray.append(Pcd)
499
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 == ''):
502 #
503 # Fix the optional data of VPD PCD.
504 #
505 if (Pcd.DatumType.strip() != "VOID*"):
506 if Sku.DefaultValue == '':
507 Pcd.SkuInfoList[Pcd.SkuInfoList.keys()[0]].DefaultValue = Pcd.MaxDatumSize
508 Pcd.MaxDatumSize = None
509 else:
510 EdkLogger.error("build", AUTOGEN_ERROR, "PCD setting error",
511 File=self.MetaFile,
512 ExtraData="\n\tPCD: %s.%s format incorrect in DSC: %s\n\t\t\n"
513 % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, self.Platform.MetaFile.Path))
514
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
519
520 #
521 # Fix the PCDs define in VPD PCD section that never referenced by module.
522 # An example is PCD for signature usage.
523 #
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 == ''):
528 FoundFlag = False
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):
533 FoundFlag = True
534
535 # Not found, it should be signature
536 if not FoundFlag :
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()
540
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
550
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
555
556
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))
561
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):
567 try:
568 os.makedirs(FvPath)
569 except:
570 EdkLogger.error("build", FILE_WRITE_FAILURE, "Fail to create FV folder under %s" % self.BuildDir)
571
572 VpdFileName = self.Platform.VpdFileName
573 if VpdFileName == None or VpdFileName == "" :
574 VpdFilePath = os.path.join(FvPath, "%s.txt" % self.Platform.VpdToolGuid)
575 else :
576 VpdFilePath = os.path.join(FvPath, "%s.txt" % VpdFileName)
577
578 if not os.path.exists(VpdFilePath) or os.path.getmtime(VpdFilePath) < DscTimeStamp:
579 VpdFile.Write(VpdFilePath)
580
581 # retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.
582 BPDGToolName = None
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"]
588 break
589 # Call third party GUID BPDG tool.
590 if BPDGToolName != None:
591 VpdInfoFile.CallExtenalBPDGTool(BPDGToolName, VpdFilePath, VpdFileName)
592 else:
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.")
594
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)
599 else :
600 VpdMapFilePath = os.path.join(self.BuildDir, "FV", "%s.map" % VpdFileName)
601 if os.path.exists(VpdMapFilePath):
602 VpdFile.Read(VpdMapFilePath)
603
604 # Fixup "*" offset
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]
610 else:
611 EdkLogger.error("build", FILE_READ_FAILURE, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath)
612
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)
618
619
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
625
626 ## Return platform name
627 def _GetName(self):
628 return self.Platform.PlatformName
629
630 ## Return the meta file GUID
631 def _GetGuid(self):
632 return self.Platform.Guid
633
634 ## Return the platform version
635 def _GetVersion(self):
636 return self.Platform.Version
637
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)
643 else:
644 self._FdfFile = ''
645 return self._FdfFile
646
647 ## Return the build output directory platform specifies
648 def _GetOutputDir(self):
649 return self.Platform.OutputDirectory
650
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,
658 )
659 else:
660 self._BuildDir = path.join(
661 self.WorkspaceDir,
662 self.OutputDir,
663 self.BuildTarget + "_" + self.ToolChain,
664 )
665 return self._BuildDir
666
667 ## Return directory of platform makefile
668 #
669 # @retval string Makefile directory
670 #
671 def _GetMakeFileDir(self):
672 if self._MakeFileDir == None:
673 self._MakeFileDir = path.join(self.BuildDir, self.Arch)
674 return self._MakeFileDir
675
676 ## Return build command string
677 #
678 # @retval string Build command string
679 #
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()
687 if NewOption != '':
688 self._BuildCommand += SplitOption(NewOption)
689 return self._BuildCommand
690
691 ## Get tool chain definition
692 #
693 # Get each tool defition for given tool chain from tools_def.txt and platform
694 #
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 = {}
702 DllPathList = set()
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:
706 continue
707
708 Value = ToolDefinition[Def]
709 # don't record the DLL
710 if Attr == "DLL":
711 DllPathList.add(Value)
712 continue
713
714 if Tool not in self._ToolDefinitions:
715 self._ToolDefinitions[Tool] = {}
716 self._ToolDefinitions[Tool][Attr] = Value
717
718 ToolsDef = ''
719 MakePath = ''
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"
724 MakeFlags = ''
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:]
732 else:
733 Value += " " + self.BuildOption[Tool][Attr]
734
735 if Attr == "PATH":
736 # Don't put MAKE definition in the file
737 if Tool == "MAKE":
738 MakePath = Value
739 else:
740 ToolsDef += "%s = %s\n" % (Tool, Value)
741 elif Attr != "DLL":
742 # Don't put MAKE definition in the file
743 if Tool == "MAKE":
744 if Attr == "FLAGS":
745 MakeFlags = Value
746 else:
747 ToolsDef += "%s_%s = %s\n" % (Tool, Attr, Value)
748 ToolsDef += "\n"
749
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
754
755 return self._ToolDefinitions
756
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
762
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." \
771 % self.ToolChain)
772 self._ToolChainFamily = "MSFT"
773 else:
774 self._ToolChainFamily = ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]
775 return self._ToolChainFamily
776
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." \
784 % self.ToolChain)
785 self._BuildRuleFamily = "MSFT"
786 else:
787 self._BuildRuleFamily = ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]
788 return self._BuildRuleFamily
789
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
795
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
801
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
807
808 ## Parse build_rule.txt in $(WORKSPACE)/Conf/build_rule.txt
809 #
810 # @retval BuildRule object
811 #
812 def _GetBuildRule(self):
813 if self._BuildRule == None:
814 BuildRuleFile = 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
821
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
832
833 ## Get list of non-dynamic PCDs
834 def _GetNonDynamicPcdList(self):
835 if self._NonDynamicPcdList == None:
836 self.CollectPlatformDynamicPcds()
837 return self._NonDynamicPcdList
838
839 ## Get list of dynamic PCDs
840 def _GetDynamicPcdList(self):
841 if self._DynamicPcdList == None:
842 self.CollectPlatformDynamicPcds()
843 return self._DynamicPcdList
844
845 ## Generate Token Number for all PCD
846 def _GetPcdTokenNumbers(self):
847 if self._PcdTokenNumber == None:
848 self._PcdTokenNumber = sdict()
849 TokenNumber = 1
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
854 TokenNumber += 1
855
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
860 TokenNumber += 1
861
862 for Pcd in self.NonDynamicPcdList:
863 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
864 TokenNumber += 1
865 return self._PcdTokenNumber
866
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:
872 Ma = ModuleAutoGen(
873 self.Workspace,
874 ModuleFile,
875 self.BuildTarget,
876 self.ToolChain,
877 self.Arch,
878 self.MetaFile
879 )
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)
885
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
891
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
897
898 ## Test if a module is supported by the platform
899 #
900 # An error will be raised directly if the module or its arch is not supported
901 # by the platform or current configuration
902 #
903 def ValidModule(self, Module):
904 return Module in self.Platform.Modules or Module in self.Platform.LibraryInstances
905
906 ## Resolve the library classes in a module to library instances
907 #
908 # This method will not only resolve library classes but also sort the library
909 # instances according to the dependency-ship.
910 #
911 # @param Module The module from which the library classes will be resolved
912 #
913 # @retval library_list List of library instances sorted
914 #
915 def ApplyLibraryInstance(self, Module):
916 ModuleType = Module.ModuleType
917
918 # for overridding library instances with module specific setting
919 PlatformModule = self.Platform.Modules[str(Module)]
920
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]
925
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]
930
931 # R9 module
932 LibraryConsumerList = [Module]
933 Constructor = []
934 ConsumedByList = sdict()
935 LibraryInstance = sdict()
936
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]
946 else:
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,
953 File=self.MetaFile,
954 ExtraData="in [%s] [%s]\n\tconsumed by module [%s]" % (str(M), self.Arch, str(Module)))
955
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))
969
970 LibraryInstance[LibraryClassName] = LibraryModule
971 LibraryConsumerList.append(LibraryModule)
972 EdkLogger.verbose("\t" + str(LibraryClassName) + " : " + str(LibraryModule))
973 else:
974 LibraryModule = LibraryInstance[LibraryClassName]
975
976 if LibraryModule == None:
977 continue
978
979 if LibraryModule.ConstructorList != [] and LibraryModule not in Constructor:
980 Constructor.append(LibraryModule)
981
982 if LibraryModule not in ConsumedByList:
983 ConsumedByList[LibraryModule] = []
984 # don't add current module itself to consumer list
985 if M != Module:
986 if M in ConsumedByList[LibraryModule]:
987 continue
988 ConsumedByList[LibraryModule].append(M)
989 #
990 # Initialize the sorted output list to the empty set
991 #
992 SortedLibraryList = []
993 #
994 # Q <- Set of all nodes with no incoming edges
995 #
996 LibraryList = [] #LibraryInstance.values()
997 Q = []
998 for LibraryClassName in LibraryInstance:
999 M = LibraryInstance[LibraryClassName]
1000 LibraryList.append(M)
1001 if ConsumedByList[M] == []:
1002 Q.append(M)
1003
1004 #
1005 # start the DAG algorithm
1006 #
1007 while True:
1008 EdgeRemoved = True
1009 while Q == [] and EdgeRemoved:
1010 EdgeRemoved = False
1011 # for each node Item with a Constructor
1012 for Item in LibraryList:
1013 if Item not in Constructor:
1014 continue
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:
1018 continue
1019 # remove edge e from the graph if Node has no constructor
1020 ConsumedByList[Item].remove(Node)
1021 EdgeRemoved = True
1022 if ConsumedByList[Item] == []:
1023 # insert Item into Q
1024 Q.insert(0, Item)
1025 break
1026 if Q != []:
1027 break
1028 # DAG is done if there's no more incoming edge for all nodes
1029 if Q == []:
1030 break
1031
1032 # remove node from Q
1033 Node = Q.pop()
1034 # output Node
1035 SortedLibraryList.append(Node)
1036
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]:
1040 continue
1041 # remove edge e from the graph
1042 ConsumedByList[Item].remove(Node)
1043
1044 if ConsumedByList[Item] != []:
1045 continue
1046 # insert Item into Q, if Item has no other incoming edges
1047 Q.insert(0, Item)
1048
1049 #
1050 # if any remaining node Item in the graph has a constructor and an incoming edge, then the graph has a cycle
1051 #
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)
1059
1060 #
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
1063 #
1064 SortedLibraryList.reverse()
1065 return SortedLibraryList
1066
1067
1068 ## Override PCD setting (type, value, ...)
1069 #
1070 # @param ToPcd The PCD to be overrided
1071 # @param FromPcd The PCD overrideing from
1072 #
1073 def _OverridePcd(self, ToPcd, FromPcd, Module=""):
1074 #
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
1077 # package
1078 #
1079 if FromPcd != None:
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),
1092 File=self.MetaFile)
1093
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
1106
1107 # check the validation of datum
1108 IsValid, Cause = CheckPcdDatum(ToPcd.DatumType, ToPcd.DefaultValue)
1109 if not IsValid:
1110 EdkLogger.error('build', FORMAT_INVALID, Cause, File=self.MetaFile,
1111 ExtraData="%s.%s" % (ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName))
1112
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(',')))
1123 else:
1124 ToPcd.MaxDatumSize = str(len(Value))
1125
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
1131 else:
1132 SkuName = 'DEFAULT'
1133 ToPcd.SkuInfoList = {
1134 SkuName : SkuInfoClass(SkuName, self.Platform.SkuIds[SkuName], '', '', '', '', '', ToPcd.DefaultValue)
1135 }
1136
1137 ## Apply PCD setting defined platform to a module
1138 #
1139 # @param Module The module from which the PCD setting will be overrided
1140 #
1141 # @retval PCD_list The list PCDs with settings from platform
1142 #
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]
1150 else:
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])
1161 EdkLogger.error(
1162 'build',
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)),
1167 File=self.MetaFile
1168 )
1169
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:
1174 if Key in Pcds:
1175 self._OverridePcd(Pcds[Key], PlatformModule.Pcds[Key], Module)
1176 return Pcds.values()
1177
1178 ## Resolve library names to library modules
1179 #
1180 # (for R8.x modules)
1181 #
1182 # @param Module The module from which the library names will be resolved
1183 #
1184 # @retval library_list The list of library modules
1185 #
1186 def ResolveLibraryReference(self, Module):
1187 EdkLogger.verbose("")
1188 EdkLogger.verbose("Library instances of module [%s] [%s]:" % (str(Module), self.Arch))
1189 LibraryConsumerList = [Module]
1190
1191 # "CompilerStub" is a must for R8 modules
1192 if Module.Libraries:
1193 Module.Libraries.append("CompilerStub")
1194 LibraryList = []
1195 while len(LibraryConsumerList) > 0:
1196 M = LibraryConsumerList.pop()
1197 for LibraryName in M.Libraries:
1198 Library = self.Platform.LibraryClasses[LibraryName, ':dummy:']
1199 if Library == None:
1200 for Key in self.Platform.LibraryClasses.data.keys():
1201 if LibraryName.upper() == Key.upper():
1202 Library = self.Platform.LibraryClasses[Key, ':dummy:']
1203 break
1204 if Library == None:
1205 EdkLogger.warn("build", "Library [%s] is not found" % LibraryName, File=str(M),
1206 ExtraData="\t%s [%s]" % (str(Module), self.Arch))
1207 continue
1208
1209 if Library not in LibraryList:
1210 LibraryList.append(Library)
1211 LibraryConsumerList.append(Library)
1212 EdkLogger.verbose("\t" + LibraryName + " : " + str(Library) + ' ' + str(type(Library)))
1213 return LibraryList
1214
1215 ## Expand * in build option key
1216 #
1217 # @param Options Options to be expanded
1218 #
1219 # @retval options Options expanded
1220 #
1221 def _ExpandBuildOption(self, Options, ModuleStyle=None):
1222 BuildOptions = {}
1223 FamilyMatch = False
1224 FamilyIsNull = True
1225 for Key in Options:
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:
1230 continue
1231 elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:
1232 continue
1233 Family = Key[0]
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]:
1240 continue
1241 elif Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_FAMILY]:
1242 continue
1243 FamilyMatch = True
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]
1252 else:
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:
1257 return BuildOptions
1258
1259 for Key in Options:
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:
1264 continue
1265 elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:
1266 continue
1267 Family = Key[0]
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 =="":
1271 continue
1272 # option has been added before
1273 if Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_FAMILY]:
1274 continue
1275
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]
1284 else:
1285 # append options for the same tool
1286 BuildOptions[Tool][Attr] += " " + Options[Key]
1287 return BuildOptions
1288
1289 ## Append build options in platform to a module
1290 #
1291 # @param Module The module to which the build options will be appened
1292 #
1293 # @retval options The options appended with build options in platform
1294 #
1295 def ApplyBuildOption(self, Module):
1296 # Get the different options for the different style module
1297 if Module.AutoGenVersion < 0x00010005:
1298 PlatformOptions = self.EdkBuildOption
1299 else:
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)
1305 else:
1306 PlatformModuleOptions = {}
1307
1308 AllTools = set(ModuleOptions.keys() + PlatformOptions.keys() + PlatformModuleOptions.keys() + self.ToolDefinition.keys())
1309 BuildOptions = {}
1310 for Tool in AllTools:
1311 if Tool not in BuildOptions:
1312 BuildOptions[Tool] = {}
1313
1314 for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, PlatformModuleOptions]:
1315 if Tool not in Options:
1316 continue
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:]
1324 else:
1325 BuildOptions[Tool][Attr] += " " + Value
1326 if Module.AutoGenVersion < 0x00010005 and self.Workspace.UniFlag != None:
1327 #
1328 # Override UNI flag only for EDK module.
1329 #
1330 if 'BUILD' not in BuildOptions:
1331 BuildOptions['BUILD'] = {}
1332 BuildOptions['BUILD']['FLAGS'] = self.Workspace.UniFlag
1333 return BuildOptions
1334
1335 Platform = property(_GetPlatform)
1336 Name = property(_GetName)
1337 Guid = property(_GetGuid)
1338 Version = property(_GetVersion)
1339
1340 OutputDir = property(_GetOutputDir)
1341 BuildDir = property(_GetBuildDir)
1342 MakeFileDir = property(_GetMakeFileDir)
1343 FdfFile = property(_GetFdfFile)
1344
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)
1349
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
1357
1358 BuildCommand = property(_GetBuildCommand)
1359 BuildRule = property(_GetBuildRule)
1360 ModuleAutoGenList = property(_GetModuleAutoGenList)
1361 LibraryAutoGenList = property(_GetLibraryAutoGenList)
1362
1363 ## ModuleAutoGen class
1364 #
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.
1368 #
1369 class ModuleAutoGen(AutoGen):
1370 ## The real constructor of ModuleAutoGen
1371 #
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
1375 #
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
1382 #
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)
1386
1387 self.Workspace = Workspace
1388 self.WorkspaceDir = Workspace.WorkspaceDir
1389
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))
1396 return False
1397
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]
1403
1404 self.ToolChain = Toolchain
1405 self.BuildTarget = Target
1406 self.Arch = Arch
1407 self.ToolChainFamily = self.PlatformInfo.ToolChainFamily
1408 self.BuildRuleFamily = self.PlatformInfo.BuildRuleFamily
1409
1410 self.IsMakeFileCreated = False
1411 self.IsCodeFileCreated = False
1412
1413 self.BuildDatabase = self.Workspace.BuildDatabase
1414
1415 self._Module = None
1416 self._Name = None
1417 self._Guid = None
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
1425 self._Macro = None
1426
1427 self._BuildDir = None
1428 self._OutputDir = None
1429 self._DebugDir = None
1430 self._MakeFileDir = None
1431
1432 self._IncludePathList = None
1433 self._AutoGenFileList = None
1434 self._UnicodeFileList = None
1435 self._SourceFileList = None
1436 self._ObjectFileList = None
1437 self._BinaryFileList = None
1438
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
1456
1457 return True
1458
1459 def __repr__(self):
1460 return "%s [%s]" % (self.MetaFile, self.Arch)
1461
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
1475
1476 self._Macro["BASE_NAME" ] = self.Name
1477
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
1482
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
1489 return self._Macro
1490
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]
1495 return self._Module
1496
1497 ## Return the module name
1498 def _GetBaseName(self):
1499 return self.Module.BaseName
1500
1501 ## Return the module SourceOverridePath
1502 def _GetSourceOverridePath(self):
1503 return self.Module.SourceOverridePath
1504
1505 ## Return the module meta-file GUID
1506 def _GetGuid(self):
1507 return self.Module.Guid
1508
1509 ## Return the module version
1510 def _GetVersion(self):
1511 return self.Module.Version
1512
1513 ## Return the module type
1514 def _GetModuleType(self):
1515 return self.Module.ModuleType
1516
1517 ## Return the component type (for R8.x style of module)
1518 def _GetComponentType(self):
1519 return self.Module.ComponentType
1520
1521 ## Return the build type
1522 def _GetBuildType(self):
1523 return self.Module.BuildType
1524
1525 ## Return the PCD_IS_DRIVER setting
1526 def _GetPcdIsDriver(self):
1527 return self.Module.PcdIsDriver
1528
1529 ## Return the autogen version, i.e. module meta-file version
1530 def _GetAutoGenVersion(self):
1531 return self.Module.AutoGenVersion
1532
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
1538 else:
1539 self._LibraryFlag = False
1540 return self._LibraryFlag
1541
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,
1547 self.Arch,
1548 self.SourceDir,
1549 self.MetaFile.BaseName
1550 )
1551 CreateDirectory(self._BuildDir)
1552 return self._BuildDir
1553
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
1560
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
1567
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]
1575 else:
1576 MakeType = 'nmake'
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])
1581 else:
1582 File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])
1583 self._CustomMakefile[MakeType] = File
1584 return self._CustomMakefile
1585
1586 ## Return the directory of the makefile
1587 #
1588 # @retval string The directory string of module's makefile
1589 #
1590 def _GetMakeFileDir(self):
1591 return self.BuildDir
1592
1593 ## Return build command string
1594 #
1595 # @retval string Build command string
1596 #
1597 def _GetBuildCommand(self):
1598 return self.PlatformInfo.BuildCommand
1599
1600 ## Get object list of all packages the module and its dependent libraries belong to
1601 #
1602 # @retval list The list of package object
1603 #
1604 def _GetDerivedPackageList(self):
1605 PackageList = []
1606 for M in [self.Module] + self.DependentLibraryList:
1607 for Package in M.Packages:
1608 if Package in PackageList:
1609 continue
1610 PackageList.append(Package)
1611 return PackageList
1612
1613 ## Merge dependency expression
1614 #
1615 # @retval list The token list of the dependency expression after parsed
1616 #
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
1622
1623 self._DepexList[self.ModuleType] = []
1624
1625 for ModuleType in self._DepexList:
1626 DepexList = self._DepexList[ModuleType]
1627 #
1628 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
1629 #
1630 for M in [self.Module] + self.DependentLibraryList:
1631 Inherited = False
1632 for D in M.Depex[self.Arch, ModuleType]:
1633 if DepexList != []:
1634 DepexList.append('AND')
1635 DepexList.append('(')
1636 DepexList.extend(D)
1637 if DepexList[-1] == 'END': # no need of a END at this time
1638 DepexList.pop()
1639 DepexList.append(')')
1640 Inherited = True
1641 if Inherited:
1642 EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexList))
1643 if 'BEFORE' in DepexList or 'AFTER' in DepexList:
1644 break
1645 if len(DepexList) > 0:
1646 EdkLogger.verbose('')
1647 return self._DepexList
1648
1649 ## Merge dependency expression
1650 #
1651 # @retval list The token list of the dependency expression after parsed
1652 #
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
1658
1659 self._DepexExpressionList[self.ModuleType] = ''
1660
1661 for ModuleType in self._DepexExpressionList:
1662 DepexExpressionList = self._DepexExpressionList[ModuleType]
1663 #
1664 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
1665 #
1666 for M in [self.Module] + self.DependentLibraryList:
1667 Inherited = False
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 += ')'
1675 Inherited = True
1676 if Inherited:
1677 EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexExpressionList))
1678 if 'BEFORE' in DepexExpressionList or 'AFTER' in DepexExpressionList:
1679 break
1680 if len(DepexExpressionList) > 0:
1681 EdkLogger.verbose('')
1682 self._DepexExpressionList[ModuleType] = DepexExpressionList
1683 return self._DepexExpressionList
1684
1685 ## Return the list of specification version required for the module
1686 #
1687 # @retval list The list of specification defined in module file
1688 #
1689 def _GetSpecification(self):
1690 return self.Module.Specification
1691
1692 ## Tool option for the module build
1693 #
1694 # @param PlatformInfo The object of PlatformBuildInfo
1695 # @retval dict The dict containing valid options
1696 #
1697 def _GetModuleBuildOption(self):
1698 if self._BuildOption == None:
1699 self._BuildOption = self.PlatformInfo.ApplyBuildOption(self.Module)
1700 return self._BuildOption
1701
1702 ## Return a list of files which can be built from source
1703 #
1704 # What kind of files can be built is determined by build rules in
1705 # $(WORKSPACE)/Conf/build_rule.txt and toolchain family.
1706 #
1707 def _GetSourceFileList(self):
1708 if self._SourceFileList == None:
1709 self._SourceFileList = []
1710 for F in self.Module.Sources:
1711 # match tool chain
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))
1715 continue
1716 # match tool chain family
1717 if F.ToolChainFamily != "" and F.ToolChainFamily != self.ToolChainFamily:
1718 EdkLogger.debug(
1719 EdkLogger.DEBUG_0,
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))
1723 continue
1724
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
1731
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]
1737 else:
1738 self._UnicodeFileList = []
1739 return self._UnicodeFileList
1740
1741 ## Return a list of files which can be built from binary
1742 #
1743 # "Build" binary files are just to copy them to build directory.
1744 #
1745 # @retval list The list of files which can be built later
1746 #
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:
1752 continue
1753 self._BinaryFileList.append(F)
1754 self._ApplyBuildRule(F, F.Type)
1755 return self._BinaryFileList
1756
1757 def _GetBuildRules(self):
1758 if self._BuildRules == None:
1759 BuildRules = {}
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]
1764 if not RuleObject:
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
1769 if not RuleObject:
1770 RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.ToolChainFamily]
1771 if not RuleObject:
1772 # build type is always module type, but ...
1773 if self.ModuleType != self.BuildType:
1774 RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.ToolChainFamily]
1775 if not RuleObject:
1776 continue
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
1783
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 = {}
1790
1791 LastTarget = None
1792 RuleChain = []
1793 SourceList = [File]
1794 Index = 0
1795 while Index < len(SourceList):
1796 Source = SourceList[Index]
1797 Index = Index + 1
1798
1799 if Source != File:
1800 CreateDirectory(Source.Dir)
1801
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]
1808 else:
1809 # stop at no more rules
1810 if LastTarget:
1811 self._FinalBuildTargetList.add(LastTarget)
1812 break
1813
1814 FileType = RuleObject.SourceFileType
1815 if FileType not in self._FileTypes:
1816 self._FileTypes[FileType] = set()
1817 self._FileTypes[FileType].add(Source)
1818
1819 # stop at STATIC_LIBRARY for library
1820 if self.IsLibrary and FileType == TAB_STATIC_LIBRARY:
1821 if LastTarget:
1822 self._FinalBuildTargetList.add(LastTarget)
1823 break
1824
1825 Target = RuleObject.Apply(Source)
1826 if not Target:
1827 if LastTarget:
1828 self._FinalBuildTargetList.add(LastTarget)
1829 break
1830 elif not Target.Outputs:
1831 # Only do build for target with outputs
1832 self._FinalBuildTargetList.add(Target)
1833
1834 if FileType not in self._BuildTargets:
1835 self._BuildTargets[FileType] = set()
1836 self._BuildTargets[FileType].add(Target)
1837
1838 if not Source.IsBinary and Source == File:
1839 self._IntroBuildTargetList.add(Target)
1840
1841 # to avoid cyclic rule
1842 if FileType in RuleChain:
1843 break
1844
1845 RuleChain.append(FileType)
1846 SourceList.extend(Target.Outputs)
1847 LastTarget = Target
1848 FileType = TAB_UNKNOWN_FILE
1849
1850 def _GetTargets(self):
1851 if self._BuildTargets == None:
1852 self._IntroBuildTargetList = set()
1853 self._FinalBuildTargetList = set()
1854 self._BuildTargets = {}
1855 self._FileTypes = {}
1856
1857 #TRICK: call _GetSourceFileList to apply build rule for binary files
1858 if self.SourceFileList:
1859 pass
1860
1861 #TRICK: call _GetBinaryFileList to apply build rule for binary files
1862 if self.BinaryFileList:
1863 pass
1864
1865 return self._BuildTargets
1866
1867 def _GetIntroTargetList(self):
1868 self._GetTargets()
1869 return self._IntroBuildTargetList
1870
1871 def _GetFinalTargetList(self):
1872 self._GetTargets()
1873 return self._FinalBuildTargetList
1874
1875 def _GetFileTypes(self):
1876 self._GetTargets()
1877 return self._FileTypes
1878
1879 ## Get the list of package object the module depends on
1880 #
1881 # @retval list The package object list
1882 #
1883 def _GetDependentPackageList(self):
1884 return self.Module.Packages
1885
1886 ## Return the list of auto-generated code file
1887 #
1888 # @retval list The list of auto-generated file
1889 #
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
1922
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
1927 if self.IsLibrary:
1928 self._DependentLibraryList = []
1929 else:
1930 if self.AutoGenVersion < 0x00010005:
1931 self._DependentLibraryList = self.PlatformInfo.ResolveLibraryReference(self.Module)
1932 else:
1933 self._DependentLibraryList = self.PlatformInfo.ApplyLibraryInstance(self.Module)
1934 return self._DependentLibraryList
1935
1936 ## Get the list of PCDs from current module
1937 #
1938 # @retval list The list of PCD
1939 #
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
1945
1946 ## Get the list of PCDs from dependent libraries
1947 #
1948 # @retval list The list of PCD
1949 #
1950 def _GetLibraryPcdList(self):
1951 if self._LibraryPcdList == None:
1952 Pcds = {}
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:
1959 continue
1960 Pcds[Key] = copy.copy(Library.Pcds[Key])
1961 # apply PCD settings from platform
1962 self._LibraryPcdList = self.PlatformInfo.ApplyPcdSetting(self.Module, Pcds)
1963 else:
1964 self._LibraryPcdList = []
1965 return self._LibraryPcdList
1966
1967 ## Get the GUID value mapping
1968 #
1969 # @retval dict The mapping between GUID cname and its value
1970 #
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
1977
1978 ## Get the protocol value mapping
1979 #
1980 # @retval dict The mapping between protocol cname and its value
1981 #
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
1988
1989 ## Get the PPI value mapping
1990 #
1991 # @retval dict The mapping between PPI cname and its value
1992 #
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
1999
2000 ## Get the list of include search path
2001 #
2002 # @retval list The list path
2003 #
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)
2011 # for r8 modules
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)
2017 else:
2018 self._IncludePathList.append(self.MetaFile.Dir)
2019 self._IncludePathList.append(self.DebugDir)
2020
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
2029
2030 ## Create makefile for the module and its dependent libraries
2031 #
2032 # @param CreateLibraryMakeFile Flag indicating if or not the makefiles of
2033 # dependent libraries will be created
2034 #
2035 def CreateMakeFile(self, CreateLibraryMakeFile=True):
2036 if self.IsMakeFileCreated:
2037 return
2038
2039 if not self.IsLibrary and CreateLibraryMakeFile:
2040 for LibraryAutoGen in self.LibraryAutoGenList:
2041 LibraryAutoGen.CreateMakeFile()
2042
2043 if len(self.CustomMakefile) == 0:
2044 Makefile = GenMake.ModuleMakefile(self)
2045 else:
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))
2050 else:
2051 EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of makefile for module %s [%s]" %
2052 (self.Name, self.Arch))
2053
2054 self.IsMakeFileCreated = True
2055
2056 ## Create autogen code for the module and its dependent libraries
2057 #
2058 # @param CreateLibraryCodeFile Flag indicating if or not the code of
2059 # dependent libraries will be created
2060 #
2061 def CreateCodeFile(self, CreateLibraryCodeFile=True):
2062 if self.IsCodeFileCreated:
2063 return
2064
2065 if not self.IsLibrary and CreateLibraryCodeFile:
2066 for LibraryAutoGen in self.LibraryAutoGenList:
2067 LibraryAutoGen.CreateCodeFile()
2068
2069 AutoGenList = []
2070 IgoredAutoGenList = []
2071
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':
2076 continue
2077
2078 AutoGenList.append(str(File))
2079 else:
2080 IgoredAutoGenList.append(str(File))
2081
2082 # Skip the following code for EDK I inf
2083 if self.AutoGenVersion < 0x00010005:
2084 return
2085
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":
2089 continue
2090
2091 Dpx = GenDepex.DependencyExpression(self.DepexList[ModuleType], ModuleType, True)
2092 DpxFile = gAutoGenDepexFileName % {"module_name" : self.Name}
2093
2094 if Dpx.Generate(path.join(self.OutputDir, DpxFile)):
2095 AutoGenList.append(str(DpxFile))
2096 else:
2097 IgoredAutoGenList.append(str(DpxFile))
2098
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))
2105 else:
2106 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated [%s] (skipped %s) files for module %s [%s]" %
2107 (" ".join(AutoGenList), " ".join(IgoredAutoGenList), self.Name, self.Arch))
2108
2109 self.IsCodeFileCreated = True
2110 return AutoGenList
2111
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:
2117 La = ModuleAutoGen(
2118 self.Workspace,
2119 Library.MetaFile,
2120 self.BuildTarget,
2121 self.ToolChain,
2122 self.Arch,
2123 self.PlatformInfo.MetaFile
2124 )
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
2130
2131 ## Return build command string
2132 #
2133 # @retval string Build command string
2134 #
2135 def _GetBuildCommand(self):
2136 return self.PlatformInfo.BuildCommand
2137
2138
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)
2150
2151 IsLibrary = property(_IsLibrary)
2152
2153 BuildDir = property(_GetBuildDir)
2154 OutputDir = property(_GetOutputDir)
2155 DebugDir = property(_GetDebugDir)
2156 MakeFileDir = property(_GetMakeFileDir)
2157 CustomMakefile = property(_GetCustomMakefile)
2158
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)
2169
2170 DependentPackageList = property(_GetDependentPackageList)
2171 DependentLibraryList = property(_GetLibraryList)
2172 LibraryAutoGenList = property(_GetLibraryAutoGenList)
2173 DerivedPackageList = property(_GetDerivedPackageList)
2174
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)
2184
2185 # This acts like the main() function for the script, unless it is 'import'ed into another script.
2186 if __name__ == '__main__':
2187 pass
2188