]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/AutoGen/AutoGen.py
Sync EDKII BaseTools to BaseTools project r2065.
[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 #
166 # Make global macros available when parsing FDF file
167 #
168 InputMacroDict.update(self.BuildDatabase.WorkspaceDb._GlobalMacros)
169 Fdf = FdfParser(self.FdfFile.Path)
170 Fdf.ParseFile()
171 PcdSet = Fdf.Profile.PcdDict
172 ModuleList = Fdf.Profile.InfList
173 self.FdfProfile = Fdf.Profile
174 else:
175 PcdSet = {}
176 ModuleList = []
177 self.FdfProfile = None
178
179 # apply SKU and inject PCDs from Flash Definition file
180 for Arch in self.ArchList:
181 Platform = self.BuildDatabase[self.MetaFile, Arch]
182 Platform.SkuName = self.SkuId
183 for Name, Guid in PcdSet:
184 Platform.AddPcd(Name, Guid, PcdSet[Name, Guid])
185
186 Pa = PlatformAutoGen(self, self.MetaFile, Target, Toolchain, Arch)
187 #
188 # Explicitly collect platform's dynamic PCDs
189 #
190 Pa.CollectPlatformDynamicPcds()
191 self.AutoGenObjectList.append(Pa)
192
193 self._BuildDir = None
194 self._FvDir = None
195 self._MakeFileDir = None
196 self._BuildCommand = None
197
198 return True
199
200 def __repr__(self):
201 return "%s [%s]" % (self.MetaFile, ", ".join(self.ArchList))
202
203 ## Return the directory to store FV files
204 def _GetFvDir(self):
205 if self._FvDir == None:
206 self._FvDir = path.join(self.BuildDir, 'FV')
207 return self._FvDir
208
209 ## Return the directory to store all intermediate and final files built
210 def _GetBuildDir(self):
211 return self.AutoGenObjectList[0].BuildDir
212
213 ## Return the build output directory platform specifies
214 def _GetOutputDir(self):
215 return self.Platform.OutputDirectory
216
217 ## Return platform name
218 def _GetName(self):
219 return self.Platform.PlatformName
220
221 ## Return meta-file GUID
222 def _GetGuid(self):
223 return self.Platform.Guid
224
225 ## Return platform version
226 def _GetVersion(self):
227 return self.Platform.Version
228
229 ## Return paths of tools
230 def _GetToolDefinition(self):
231 return self.AutoGenObjectList[0].ToolDefinition
232
233 ## Return directory of platform makefile
234 #
235 # @retval string Makefile directory
236 #
237 def _GetMakeFileDir(self):
238 if self._MakeFileDir == None:
239 self._MakeFileDir = self.BuildDir
240 return self._MakeFileDir
241
242 ## Return build command string
243 #
244 # @retval string Build command string
245 #
246 def _GetBuildCommand(self):
247 if self._BuildCommand == None:
248 # BuildCommand should be all the same. So just get one from platform AutoGen
249 self._BuildCommand = self.AutoGenObjectList[0].BuildCommand
250 return self._BuildCommand
251
252 ## Create makefile for the platform and modules in it
253 #
254 # @param CreateDepsMakeFile Flag indicating if the makefile for
255 # modules will be created as well
256 #
257 def CreateMakeFile(self, CreateDepsMakeFile=False):
258 # create makefile for platform
259 Makefile = GenMake.TopLevelMakefile(self)
260 if Makefile.Generate():
261 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated makefile for platform [%s] %s\n" %
262 (self.MetaFile, self.ArchList))
263 else:
264 EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of makefile for platform [%s] %s\n" %
265 (self.MetaFile, self.ArchList))
266
267 if CreateDepsMakeFile:
268 for Pa in self.AutoGenObjectList:
269 Pa.CreateMakeFile(CreateDepsMakeFile)
270
271 ## Create autogen code for platform and modules
272 #
273 # Since there's no autogen code for platform, this method will do nothing
274 # if CreateModuleCodeFile is set to False.
275 #
276 # @param CreateDepsCodeFile Flag indicating if creating module's
277 # autogen code file or not
278 #
279 def CreateCodeFile(self, CreateDepsCodeFile=False):
280 if not CreateDepsCodeFile:
281 return
282 for Pa in self.AutoGenObjectList:
283 Pa.CreateCodeFile(CreateDepsCodeFile)
284
285 Name = property(_GetName)
286 Guid = property(_GetGuid)
287 Version = property(_GetVersion)
288 OutputDir = property(_GetOutputDir)
289
290 ToolDefinition = property(_GetToolDefinition) # toolcode : tool path
291
292 BuildDir = property(_GetBuildDir)
293 FvDir = property(_GetFvDir)
294 MakeFileDir = property(_GetMakeFileDir)
295 BuildCommand = property(_GetBuildCommand)
296
297 ## AutoGen class for platform
298 #
299 # PlatformAutoGen class will process the original information in platform
300 # file in order to generate makefile for platform.
301 #
302 class PlatformAutoGen(AutoGen):
303 #
304 # Used to store all PCDs for both PEI and DXE phase, in order to generate
305 # correct PCD database
306 #
307 _DynaPcdList_ = []
308 _NonDynaPcdList_ = []
309
310 ## The real constructor of PlatformAutoGen
311 #
312 # This method is not supposed to be called by users of PlatformAutoGen. It's
313 # only used by factory method __new__() to do real initialization work for an
314 # object of PlatformAutoGen
315 #
316 # @param Workspace WorkspaceAutoGen object
317 # @param PlatformFile Platform file (DSC file)
318 # @param Target Build target (DEBUG, RELEASE)
319 # @param Toolchain Name of tool chain
320 # @param Arch arch of the platform supports
321 #
322 def _Init(self, Workspace, PlatformFile, Target, Toolchain, Arch):
323 EdkLogger.debug(EdkLogger.DEBUG_9, "AutoGen platform [%s] [%s]" % (PlatformFile, Arch))
324 GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (PlatformFile, Arch, Toolchain, Target)
325
326 self.MetaFile = PlatformFile
327 self.Workspace = Workspace
328 self.WorkspaceDir = Workspace.WorkspaceDir
329 self.ToolChain = Toolchain
330 self.BuildTarget = Target
331 self.Arch = Arch
332 self.SourceDir = PlatformFile.SubDir
333 self.SourceOverrideDir = None
334 self.FdTargetList = self.Workspace.FdTargetList
335 self.FvTargetList = self.Workspace.FvTargetList
336 self.AllPcdList = []
337
338 # flag indicating if the makefile/C-code file has been created or not
339 self.IsMakeFileCreated = False
340 self.IsCodeFileCreated = False
341
342 self._Platform = None
343 self._Name = None
344 self._Guid = None
345 self._Version = None
346
347 self._BuildRule = None
348 self._SourceDir = None
349 self._BuildDir = None
350 self._OutputDir = None
351 self._FvDir = None
352 self._MakeFileDir = None
353 self._FdfFile = None
354
355 self._PcdTokenNumber = None # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
356 self._DynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
357 self._NonDynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
358
359 self._ToolDefinitions = None
360 self._ToolDefFile = None # toolcode : tool path
361 self._ToolChainFamily = None
362 self._BuildRuleFamily = None
363 self._BuildOption = None # toolcode : option
364 self._EdkBuildOption = None # edktoolcode : option
365 self._EdkIIBuildOption = None # edkiitoolcode : option
366 self._PackageList = None
367 self._ModuleAutoGenList = None
368 self._LibraryAutoGenList = None
369 self._BuildCommand = None
370
371 # get the original module/package/platform objects
372 self.BuildDatabase = Workspace.BuildDatabase
373 return True
374
375 def __repr__(self):
376 return "%s [%s]" % (self.MetaFile, self.Arch)
377
378 ## Create autogen code for platform and modules
379 #
380 # Since there's no autogen code for platform, this method will do nothing
381 # if CreateModuleCodeFile is set to False.
382 #
383 # @param CreateModuleCodeFile Flag indicating if creating module's
384 # autogen code file or not
385 #
386 def CreateCodeFile(self, CreateModuleCodeFile=False):
387 # only module has code to be greated, so do nothing if CreateModuleCodeFile is False
388 if self.IsCodeFileCreated or not CreateModuleCodeFile:
389 return
390
391 for Ma in self.ModuleAutoGenList:
392 Ma.CreateCodeFile(True)
393
394 # don't do this twice
395 self.IsCodeFileCreated = True
396
397 ## Create makefile for the platform and mdoules in it
398 #
399 # @param CreateModuleMakeFile Flag indicating if the makefile for
400 # modules will be created as well
401 #
402 def CreateMakeFile(self, CreateModuleMakeFile=False):
403 if CreateModuleMakeFile:
404 for ModuleFile in self.Platform.Modules:
405 Ma = ModuleAutoGen(self.Workspace, ModuleFile, self.BuildTarget,
406 self.ToolChain, self.Arch, self.MetaFile)
407 Ma.CreateMakeFile(True)
408
409 # no need to create makefile for the platform more than once
410 if self.IsMakeFileCreated:
411 return
412
413 # create makefile for platform
414 Makefile = GenMake.PlatformMakefile(self)
415 if Makefile.Generate():
416 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated makefile for platform [%s] [%s]\n" %
417 (self.MetaFile, self.Arch))
418 else:
419 EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of makefile for platform [%s] [%s]\n" %
420 (self.MetaFile, self.Arch))
421 self.IsMakeFileCreated = True
422
423 ## Collect dynamic PCDs
424 #
425 # Gather dynamic PCDs list from each module and their settings from platform
426 # This interface should be invoked explicitly when platform action is created.
427 #
428 def CollectPlatformDynamicPcds(self):
429 # for gathering error information
430 NoDatumTypePcdList = set()
431
432 self._GuidValue = {}
433 for F in self.Platform.Modules.keys():
434 M = ModuleAutoGen(self.Workspace, F, self.BuildTarget, self.ToolChain, self.Arch, self.MetaFile)
435 #GuidValue.update(M.Guids)
436
437 self.Platform.Modules[F].M = M
438
439 for PcdFromModule in M.ModulePcdList+M.LibraryPcdList:
440 # make sure that the "VOID*" kind of datum has MaxDatumSize set
441 if PcdFromModule.DatumType == "VOID*" and PcdFromModule.MaxDatumSize == None:
442 NoDatumTypePcdList.add("%s.%s [%s]" % (PcdFromModule.TokenSpaceGuidCName, PcdFromModule.TokenCName, F))
443
444 if PcdFromModule.Type in GenC.gDynamicPcd or PcdFromModule.Type in GenC.gDynamicExPcd:
445 #
446 # If a dynamic PCD used by a PEM module/PEI module & DXE module,
447 # it should be stored in Pcd PEI database, If a dynamic only
448 # used by DXE module, it should be stored in DXE PCD database.
449 # The default Phase is DXE
450 #
451 if M.ModuleType in ["PEIM", "PEI_CORE"]:
452 PcdFromModule.Phase = "PEI"
453 if PcdFromModule not in self._DynaPcdList_:
454 self._DynaPcdList_.append(PcdFromModule)
455 elif PcdFromModule.Phase == 'PEI':
456 # overwrite any the same PCD existing, if Phase is PEI
457 Index = self._DynaPcdList_.index(PcdFromModule)
458 self._DynaPcdList_[Index] = PcdFromModule
459 elif PcdFromModule not in self._NonDynaPcdList_:
460 self._NonDynaPcdList_.append(PcdFromModule)
461
462 # print out error information and break the build, if error found
463 if len(NoDatumTypePcdList) > 0:
464 NoDatumTypePcdListString = "\n\t\t".join(NoDatumTypePcdList)
465 EdkLogger.error("build", AUTOGEN_ERROR, "PCD setting error",
466 File=self.MetaFile,
467 ExtraData="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"
468 % NoDatumTypePcdListString)
469 self._NonDynamicPcdList = self._NonDynaPcdList_
470 self._DynamicPcdList = self._DynaPcdList_
471 self.AllPcdList = self._NonDynamicPcdList + self._DynamicPcdList
472
473 #
474 # Sort dynamic PCD list to:
475 # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should
476 # try to be put header of dynamicd List
477 # 2) If PCD is HII type, the PCD item should be put after unicode type PCD
478 #
479 # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.
480 #
481 UnicodePcdArray = []
482 HiiPcdArray = []
483 OtherPcdArray = []
484 VpdFile = VpdInfoFile.VpdInfoFile()
485 NeedProcessVpdMapFile = False
486
487 if (self.Workspace.ArchList[-1] == self.Arch):
488 for Pcd in self._DynamicPcdList:
489
490 # just pick the a value to determine whether is unicode string type
491 Sku = Pcd.SkuInfoList[Pcd.SkuInfoList.keys()[0]]
492 Sku.VpdOffset = Sku.VpdOffset.strip()
493
494 PcdValue = Sku.DefaultValue
495 if Pcd.DatumType == 'VOID*' and PcdValue.startswith("L"):
496 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
497 UnicodePcdArray.append(Pcd)
498 elif len(Sku.VariableName) > 0:
499 # if found HII type PCD then insert to right of UnicodeIndex
500 HiiPcdArray.append(Pcd)
501 else:
502 OtherPcdArray.append(Pcd)
503
504 if Pcd.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:
505 if not (self.Platform.VpdToolGuid == None or self.Platform.VpdToolGuid == ''):
506 #
507 # Fix the optional data of VPD PCD.
508 #
509 if (Pcd.DatumType.strip() != "VOID*"):
510 if Sku.DefaultValue == '':
511 Pcd.SkuInfoList[Pcd.SkuInfoList.keys()[0]].DefaultValue = Pcd.MaxDatumSize
512 Pcd.MaxDatumSize = None
513 else:
514 EdkLogger.error("build", AUTOGEN_ERROR, "PCD setting error",
515 File=self.MetaFile,
516 ExtraData="\n\tPCD: %s.%s format incorrect in DSC: %s\n\t\t\n"
517 % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, self.Platform.MetaFile.Path))
518
519 VpdFile.Add(Pcd, Sku.VpdOffset)
520 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
521 if not NeedProcessVpdMapFile and Sku.VpdOffset == "*":
522 NeedProcessVpdMapFile = True
523
524 #
525 # Fix the PCDs define in VPD PCD section that never referenced by module.
526 # An example is PCD for signature usage.
527 #
528 for DscPcd in self.Platform.Pcds:
529 DscPcdEntry = self.Platform.Pcds[DscPcd]
530 if DscPcdEntry.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:
531 if not (self.Platform.VpdToolGuid == None or self.Platform.VpdToolGuid == ''):
532 FoundFlag = False
533 for VpdPcd in VpdFile._VpdArray.keys():
534 # This PCD has been referenced by module
535 if (VpdPcd.TokenSpaceGuidCName == DscPcdEntry.TokenSpaceGuidCName) and \
536 (VpdPcd.TokenCName == DscPcdEntry.TokenCName):
537 FoundFlag = True
538
539 # Not found, it should be signature
540 if not FoundFlag :
541 # just pick the a value to determine whether is unicode string type
542 Sku = DscPcdEntry.SkuInfoList[DscPcdEntry.SkuInfoList.keys()[0]]
543 Sku.VpdOffset = Sku.VpdOffset.strip()
544
545 # Need to iterate DEC pcd information to get the value & datumtype
546 for eachDec in self.PackageList:
547 for DecPcd in eachDec.Pcds:
548 DecPcdEntry = eachDec.Pcds[DecPcd]
549 if (DecPcdEntry.TokenSpaceGuidCName == DscPcdEntry.TokenSpaceGuidCName) and \
550 (DecPcdEntry.TokenCName == DscPcdEntry.TokenCName):
551 # Print warning message to let the developer make a determine.
552 EdkLogger.warn("build", "Unreferenced vpd pcd used!",
553 File=self.MetaFile, \
554 ExtraData = "PCD: %s.%s used in the DSC file %s is unreferenced." \
555 %(DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName, self.Platform.MetaFile.Path))
556
557 DscPcdEntry.DatumType = DecPcdEntry.DatumType
558 DscPcdEntry.DefaultValue = DecPcdEntry.DefaultValue
559 # Only fix the value while no value provided in DSC file.
560 if (Sku.DefaultValue == "" or Sku.DefaultValue==None):
561 DscPcdEntry.SkuInfoList[DscPcdEntry.SkuInfoList.keys()[0]].DefaultValue = DecPcdEntry.DefaultValue
562
563
564 VpdFile.Add(DscPcdEntry, Sku.VpdOffset)
565 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
566 if not NeedProcessVpdMapFile and Sku.VpdOffset == "*":
567 NeedProcessVpdMapFile = True
568
569
570 if (self.Platform.FlashDefinition == None or self.Platform.FlashDefinition == '') and \
571 VpdFile.GetCount() != 0:
572 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE,
573 "Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD." % str(self.Platform.MetaFile))
574
575 if VpdFile.GetCount() != 0:
576 WorkspaceDb = self.BuildDatabase.WorkspaceDb
577 DscTimeStamp = WorkspaceDb.GetTimeStamp(WorkspaceDb.GetFileId(str(self.Platform.MetaFile)))
578 FvPath = os.path.join(self.BuildDir, "FV")
579 if not os.path.exists(FvPath):
580 try:
581 os.makedirs(FvPath)
582 except:
583 EdkLogger.error("build", FILE_WRITE_FAILURE, "Fail to create FV folder under %s" % self.BuildDir)
584
585
586 VpdFilePath = os.path.join(FvPath, "%s.txt" % self.Platform.VpdToolGuid)
587
588
589 if not os.path.exists(VpdFilePath) or os.path.getmtime(VpdFilePath) < DscTimeStamp:
590 VpdFile.Write(VpdFilePath)
591
592 # retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.
593 BPDGToolName = None
594 for ToolDef in self.ToolDefinition.values():
595 if ToolDef.has_key("GUID") and ToolDef["GUID"] == self.Platform.VpdToolGuid:
596 if not ToolDef.has_key("PATH"):
597 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "PATH attribute was not provided for BPDG guid tool %s in tools_def.txt" % self.Platform.VpdToolGuid)
598 BPDGToolName = ToolDef["PATH"]
599 break
600 # Call third party GUID BPDG tool.
601 if BPDGToolName != None:
602 VpdInfoFile.CallExtenalBPDGTool(BPDGToolName, VpdFilePath)
603 else:
604 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.")
605
606 # Process VPD map file generated by third party BPDG tool
607 if NeedProcessVpdMapFile:
608 VpdMapFilePath = os.path.join(self.BuildDir, "FV", "%s.map" % self.Platform.VpdToolGuid)
609 if os.path.exists(VpdMapFilePath):
610 VpdFile.Read(VpdMapFilePath)
611
612 # Fixup "*" offset
613 for Pcd in self._DynamicPcdList:
614 # just pick the a value to determine whether is unicode string type
615 Sku = Pcd.SkuInfoList[Pcd.SkuInfoList.keys()[0]]
616 if Sku.VpdOffset == "*":
617 Sku.VpdOffset = VpdFile.GetOffset(Pcd)[0]
618 else:
619 EdkLogger.error("build", FILE_READ_FAILURE, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath)
620
621 # Delete the DynamicPcdList At the last time enter into this function
622 del self._DynamicPcdList[:]
623 self._DynamicPcdList.extend(UnicodePcdArray)
624 self._DynamicPcdList.extend(HiiPcdArray)
625 self._DynamicPcdList.extend(OtherPcdArray)
626
627
628 ## Return the platform build data object
629 def _GetPlatform(self):
630 if self._Platform == None:
631 self._Platform = self.BuildDatabase[self.MetaFile, self.Arch]
632 return self._Platform
633
634 ## Return platform name
635 def _GetName(self):
636 return self.Platform.PlatformName
637
638 ## Return the meta file GUID
639 def _GetGuid(self):
640 return self.Platform.Guid
641
642 ## Return the platform version
643 def _GetVersion(self):
644 return self.Platform.Version
645
646 ## Return the FDF file name
647 def _GetFdfFile(self):
648 if self._FdfFile == None:
649 if self.Workspace.FdfFile != "":
650 self._FdfFile= path.join(self.WorkspaceDir, self.Workspace.FdfFile)
651 else:
652 self._FdfFile = ''
653 return self._FdfFile
654
655 ## Return the build output directory platform specifies
656 def _GetOutputDir(self):
657 return self.Platform.OutputDirectory
658
659 ## Return the directory to store all intermediate and final files built
660 def _GetBuildDir(self):
661 if self._BuildDir == None:
662 if os.path.isabs(self.OutputDir):
663 self._BuildDir = path.join(
664 path.abspath(self.OutputDir),
665 self.BuildTarget + "_" + self.ToolChain,
666 )
667 else:
668 self._BuildDir = path.join(
669 self.WorkspaceDir,
670 self.OutputDir,
671 self.BuildTarget + "_" + self.ToolChain,
672 )
673 return self._BuildDir
674
675 ## Return directory of platform makefile
676 #
677 # @retval string Makefile directory
678 #
679 def _GetMakeFileDir(self):
680 if self._MakeFileDir == None:
681 self._MakeFileDir = path.join(self.BuildDir, self.Arch)
682 return self._MakeFileDir
683
684 ## Return build command string
685 #
686 # @retval string Build command string
687 #
688 def _GetBuildCommand(self):
689 if self._BuildCommand == None:
690 self._BuildCommand = []
691 if "MAKE" in self.ToolDefinition and "PATH" in self.ToolDefinition["MAKE"]:
692 self._BuildCommand += SplitOption(self.ToolDefinition["MAKE"]["PATH"])
693 if "FLAGS" in self.ToolDefinition["MAKE"]:
694 NewOption = self.ToolDefinition["MAKE"]["FLAGS"].strip()
695 if NewOption != '':
696 self._BuildCommand += SplitOption(NewOption)
697 return self._BuildCommand
698
699 ## Get tool chain definition
700 #
701 # Get each tool defition for given tool chain from tools_def.txt and platform
702 #
703 def _GetToolDefinition(self):
704 if self._ToolDefinitions == None:
705 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDictionary
706 if TAB_TOD_DEFINES_COMMAND_TYPE not in self.Workspace.ToolDef.ToolsDefTxtDatabase:
707 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "No tools found in configuration",
708 ExtraData="[%s]" % self.MetaFile)
709 self._ToolDefinitions = {}
710 DllPathList = set()
711 for Def in ToolDefinition:
712 Target, Tag, Arch, Tool, Attr = Def.split("_")
713 if Target != self.BuildTarget or Tag != self.ToolChain or Arch != self.Arch:
714 continue
715
716 Value = ToolDefinition[Def]
717 # don't record the DLL
718 if Attr == "DLL":
719 DllPathList.add(Value)
720 continue
721
722 if Tool not in self._ToolDefinitions:
723 self._ToolDefinitions[Tool] = {}
724 self._ToolDefinitions[Tool][Attr] = Value
725
726 ToolsDef = ''
727 MakePath = ''
728 if GlobalData.gOptions.SilentMode and "MAKE" in self._ToolDefinitions:
729 if "FLAGS" not in self._ToolDefinitions["MAKE"]:
730 self._ToolDefinitions["MAKE"]["FLAGS"] = ""
731 self._ToolDefinitions["MAKE"]["FLAGS"] += " -s"
732 MakeFlags = ''
733 for Tool in self._ToolDefinitions:
734 for Attr in self._ToolDefinitions[Tool]:
735 Value = self._ToolDefinitions[Tool][Attr]
736 if Tool in self.BuildOption and Attr in self.BuildOption[Tool]:
737 # check if override is indicated
738 if self.BuildOption[Tool][Attr].startswith('='):
739 Value = self.BuildOption[Tool][Attr][1:]
740 else:
741 Value += " " + self.BuildOption[Tool][Attr]
742
743 if Attr == "PATH":
744 # Don't put MAKE definition in the file
745 if Tool == "MAKE":
746 MakePath = Value
747 else:
748 ToolsDef += "%s = %s\n" % (Tool, Value)
749 elif Attr != "DLL":
750 # Don't put MAKE definition in the file
751 if Tool == "MAKE":
752 if Attr == "FLAGS":
753 MakeFlags = Value
754 else:
755 ToolsDef += "%s_%s = %s\n" % (Tool, Attr, Value)
756 ToolsDef += "\n"
757
758 SaveFileOnChange(self.ToolDefinitionFile, ToolsDef)
759 for DllPath in DllPathList:
760 os.environ["PATH"] = DllPath + os.pathsep + os.environ["PATH"]
761 os.environ["MAKE_FLAGS"] = MakeFlags
762
763 return self._ToolDefinitions
764
765 ## Return the paths of tools
766 def _GetToolDefFile(self):
767 if self._ToolDefFile == None:
768 self._ToolDefFile = os.path.join(self.MakeFileDir, "TOOLS_DEF." + self.Arch)
769 return self._ToolDefFile
770
771 ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
772 def _GetToolChainFamily(self):
773 if self._ToolChainFamily == None:
774 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase
775 if TAB_TOD_DEFINES_FAMILY not in ToolDefinition \
776 or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_FAMILY] \
777 or not ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]:
778 EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
779 % self.ToolChain)
780 self._ToolChainFamily = "MSFT"
781 else:
782 self._ToolChainFamily = ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]
783 return self._ToolChainFamily
784
785 def _GetBuildRuleFamily(self):
786 if self._BuildRuleFamily == None:
787 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase
788 if TAB_TOD_DEFINES_BUILDRULEFAMILY not in ToolDefinition \
789 or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY] \
790 or not ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]:
791 EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
792 % self.ToolChain)
793 self._BuildRuleFamily = "MSFT"
794 else:
795 self._BuildRuleFamily = ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]
796 return self._BuildRuleFamily
797
798 ## Return the build options specific for all modules in this platform
799 def _GetBuildOptions(self):
800 if self._BuildOption == None:
801 self._BuildOption = self._ExpandBuildOption(self.Platform.BuildOptions)
802 return self._BuildOption
803
804 ## Return the build options specific for EDK modules in this platform
805 def _GetEdkBuildOptions(self):
806 if self._EdkBuildOption == None:
807 self._EdkBuildOption = self._ExpandBuildOption(self.Platform.BuildOptions, EDK_NAME)
808 return self._EdkBuildOption
809
810 ## Return the build options specific for EDKII modules in this platform
811 def _GetEdkIIBuildOptions(self):
812 if self._EdkIIBuildOption == None:
813 self._EdkIIBuildOption = self._ExpandBuildOption(self.Platform.BuildOptions, EDKII_NAME)
814 return self._EdkIIBuildOption
815
816 ## Parse build_rule.txt in $(WORKSPACE)/Conf/build_rule.txt
817 #
818 # @retval BuildRule object
819 #
820 def _GetBuildRule(self):
821 if self._BuildRule == None:
822 BuildRuleFile = None
823 if TAB_TAT_DEFINES_BUILD_RULE_CONF in self.Workspace.TargetTxt.TargetTxtDictionary:
824 BuildRuleFile = self.Workspace.TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_BUILD_RULE_CONF]
825 if BuildRuleFile in [None, '']:
826 BuildRuleFile = gBuildRuleFile
827 self._BuildRule = BuildRule(BuildRuleFile)
828 return self._BuildRule
829
830 ## Summarize the packages used by modules in this platform
831 def _GetPackageList(self):
832 if self._PackageList == None:
833 self._PackageList = set()
834 for La in self.LibraryAutoGenList:
835 self._PackageList.update(La.DependentPackageList)
836 for Ma in self.ModuleAutoGenList:
837 self._PackageList.update(Ma.DependentPackageList)
838 self._PackageList = list(self._PackageList)
839 return self._PackageList
840
841 ## Get list of non-dynamic PCDs
842 def _GetNonDynamicPcdList(self):
843 if self._NonDynamicPcdList == None:
844 self.CollectPlatformDynamicPcds()
845 return self._NonDynamicPcdList
846
847 ## Get list of dynamic PCDs
848 def _GetDynamicPcdList(self):
849 if self._DynamicPcdList == None:
850 self.CollectPlatformDynamicPcds()
851 return self._DynamicPcdList
852
853 ## Generate Token Number for all PCD
854 def _GetPcdTokenNumbers(self):
855 if self._PcdTokenNumber == None:
856 self._PcdTokenNumber = sdict()
857 TokenNumber = 1
858 for Pcd in self.DynamicPcdList:
859 if Pcd.Phase == "PEI":
860 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
861 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
862 TokenNumber += 1
863
864 for Pcd in self.DynamicPcdList:
865 if Pcd.Phase == "DXE":
866 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
867 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
868 TokenNumber += 1
869
870 for Pcd in self.NonDynamicPcdList:
871 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
872 TokenNumber += 1
873 return self._PcdTokenNumber
874
875 ## Summarize ModuleAutoGen objects of all modules/libraries to be built for this platform
876 def _GetAutoGenObjectList(self):
877 self._ModuleAutoGenList = []
878 self._LibraryAutoGenList = []
879 for ModuleFile in self.Platform.Modules:
880 Ma = ModuleAutoGen(
881 self.Workspace,
882 ModuleFile,
883 self.BuildTarget,
884 self.ToolChain,
885 self.Arch,
886 self.MetaFile
887 )
888 if Ma not in self._ModuleAutoGenList:
889 self._ModuleAutoGenList.append(Ma)
890 for La in Ma.LibraryAutoGenList:
891 if La not in self._LibraryAutoGenList:
892 self._LibraryAutoGenList.append(La)
893
894 ## Summarize ModuleAutoGen objects of all modules to be built for this platform
895 def _GetModuleAutoGenList(self):
896 if self._ModuleAutoGenList == None:
897 self._GetAutoGenObjectList()
898 return self._ModuleAutoGenList
899
900 ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
901 def _GetLibraryAutoGenList(self):
902 if self._LibraryAutoGenList == None:
903 self._GetAutoGenObjectList()
904 return self._LibraryAutoGenList
905
906 ## Test if a module is supported by the platform
907 #
908 # An error will be raised directly if the module or its arch is not supported
909 # by the platform or current configuration
910 #
911 def ValidModule(self, Module):
912 return Module in self.Platform.Modules or Module in self.Platform.LibraryInstances
913
914 ## Resolve the library classes in a module to library instances
915 #
916 # This method will not only resolve library classes but also sort the library
917 # instances according to the dependency-ship.
918 #
919 # @param Module The module from which the library classes will be resolved
920 #
921 # @retval library_list List of library instances sorted
922 #
923 def ApplyLibraryInstance(self, Module):
924 ModuleType = Module.ModuleType
925
926 # for overridding library instances with module specific setting
927 PlatformModule = self.Platform.Modules[str(Module)]
928
929 # add forced library instances (specified under LibraryClasses sections)
930 for LibraryClass in self.Platform.LibraryClasses.GetKeys():
931 if LibraryClass.startswith("NULL"):
932 Module.LibraryClasses[LibraryClass] = self.Platform.LibraryClasses[LibraryClass]
933
934 # add forced library instances (specified in module overrides)
935 for LibraryClass in PlatformModule.LibraryClasses:
936 if LibraryClass.startswith("NULL"):
937 Module.LibraryClasses[LibraryClass] = PlatformModule.LibraryClasses[LibraryClass]
938
939 # R9 module
940 LibraryConsumerList = [Module]
941 Constructor = []
942 ConsumedByList = sdict()
943 LibraryInstance = sdict()
944
945 EdkLogger.verbose("")
946 EdkLogger.verbose("Library instances of module [%s] [%s]:" % (str(Module), self.Arch))
947 while len(LibraryConsumerList) > 0:
948 M = LibraryConsumerList.pop()
949 for LibraryClassName in M.LibraryClasses:
950 if LibraryClassName not in LibraryInstance:
951 # override library instance for this module
952 if LibraryClassName in PlatformModule.LibraryClasses:
953 LibraryPath = PlatformModule.LibraryClasses[LibraryClassName]
954 else:
955 LibraryPath = self.Platform.LibraryClasses[LibraryClassName, ModuleType]
956 if LibraryPath == None or LibraryPath == "":
957 LibraryPath = M.LibraryClasses[LibraryClassName]
958 if LibraryPath == None or LibraryPath == "":
959 EdkLogger.error("build", RESOURCE_NOT_AVAILABLE,
960 "Instance of library class [%s] is not found" % LibraryClassName,
961 File=self.MetaFile,
962 ExtraData="in [%s] [%s]\n\tconsumed by module [%s]" % (str(M), self.Arch, str(Module)))
963
964 LibraryModule = self.BuildDatabase[LibraryPath, self.Arch]
965 # for those forced library instance (NULL library), add a fake library class
966 if LibraryClassName.startswith("NULL"):
967 LibraryModule.LibraryClass.append(LibraryClassObject(LibraryClassName, [ModuleType]))
968 elif LibraryModule.LibraryClass == None \
969 or len(LibraryModule.LibraryClass) == 0 \
970 or (ModuleType != 'USER_DEFINED'
971 and ModuleType not in LibraryModule.LibraryClass[0].SupModList):
972 # only USER_DEFINED can link against any library instance despite of its SupModList
973 EdkLogger.error("build", OPTION_MISSING,
974 "Module type [%s] is not supported by library instance [%s]" \
975 % (ModuleType, LibraryPath), File=self.MetaFile,
976 ExtraData="consumed by [%s]" % str(Module))
977
978 LibraryInstance[LibraryClassName] = LibraryModule
979 LibraryConsumerList.append(LibraryModule)
980 EdkLogger.verbose("\t" + str(LibraryClassName) + " : " + str(LibraryModule))
981 else:
982 LibraryModule = LibraryInstance[LibraryClassName]
983
984 if LibraryModule == None:
985 continue
986
987 if LibraryModule.ConstructorList != [] and LibraryModule not in Constructor:
988 Constructor.append(LibraryModule)
989
990 if LibraryModule not in ConsumedByList:
991 ConsumedByList[LibraryModule] = []
992 # don't add current module itself to consumer list
993 if M != Module:
994 if M in ConsumedByList[LibraryModule]:
995 continue
996 ConsumedByList[LibraryModule].append(M)
997 #
998 # Initialize the sorted output list to the empty set
999 #
1000 SortedLibraryList = []
1001 #
1002 # Q <- Set of all nodes with no incoming edges
1003 #
1004 LibraryList = [] #LibraryInstance.values()
1005 Q = []
1006 for LibraryClassName in LibraryInstance:
1007 M = LibraryInstance[LibraryClassName]
1008 LibraryList.append(M)
1009 if ConsumedByList[M] == []:
1010 Q.append(M)
1011
1012 #
1013 # start the DAG algorithm
1014 #
1015 while True:
1016 EdgeRemoved = True
1017 while Q == [] and EdgeRemoved:
1018 EdgeRemoved = False
1019 # for each node Item with a Constructor
1020 for Item in LibraryList:
1021 if Item not in Constructor:
1022 continue
1023 # for each Node without a constructor with an edge e from Item to Node
1024 for Node in ConsumedByList[Item]:
1025 if Node in Constructor:
1026 continue
1027 # remove edge e from the graph if Node has no constructor
1028 ConsumedByList[Item].remove(Node)
1029 EdgeRemoved = True
1030 if ConsumedByList[Item] == []:
1031 # insert Item into Q
1032 Q.insert(0, Item)
1033 break
1034 if Q != []:
1035 break
1036 # DAG is done if there's no more incoming edge for all nodes
1037 if Q == []:
1038 break
1039
1040 # remove node from Q
1041 Node = Q.pop()
1042 # output Node
1043 SortedLibraryList.append(Node)
1044
1045 # for each node Item with an edge e from Node to Item do
1046 for Item in LibraryList:
1047 if Node not in ConsumedByList[Item]:
1048 continue
1049 # remove edge e from the graph
1050 ConsumedByList[Item].remove(Node)
1051
1052 if ConsumedByList[Item] != []:
1053 continue
1054 # insert Item into Q, if Item has no other incoming edges
1055 Q.insert(0, Item)
1056
1057 #
1058 # if any remaining node Item in the graph has a constructor and an incoming edge, then the graph has a cycle
1059 #
1060 for Item in LibraryList:
1061 if ConsumedByList[Item] != [] and Item in Constructor and len(Constructor) > 1:
1062 ErrorMessage = "\tconsumed by " + "\n\tconsumed by ".join([str(L) for L in ConsumedByList[Item]])
1063 EdkLogger.error("build", BUILD_ERROR, 'Library [%s] with constructors has a cycle' % str(Item),
1064 ExtraData=ErrorMessage, File=self.MetaFile)
1065 if Item not in SortedLibraryList:
1066 SortedLibraryList.append(Item)
1067
1068 #
1069 # Build the list of constructor and destructir names
1070 # The DAG Topo sort produces the destructor order, so the list of constructors must generated in the reverse order
1071 #
1072 SortedLibraryList.reverse()
1073 return SortedLibraryList
1074
1075
1076 ## Override PCD setting (type, value, ...)
1077 #
1078 # @param ToPcd The PCD to be overrided
1079 # @param FromPcd The PCD overrideing from
1080 #
1081 def _OverridePcd(self, ToPcd, FromPcd, Module=""):
1082 #
1083 # in case there's PCDs coming from FDF file, which have no type given.
1084 # at this point, ToPcd.Type has the type found from dependent
1085 # package
1086 #
1087 if FromPcd != None:
1088 if ToPcd.Pending and FromPcd.Type not in [None, '']:
1089 ToPcd.Type = FromPcd.Type
1090 elif (ToPcd.Type not in [None, '']) and (FromPcd.Type not in [None, ''])\
1091 and (ToPcd.Type != FromPcd.Type) and (ToPcd.Type in FromPcd.Type):
1092 if ToPcd.Type.strip() == "DynamicEx":
1093 ToPcd.Type = FromPcd.Type
1094 elif ToPcd.Type not in [None, ''] and FromPcd.Type not in [None, ''] \
1095 and ToPcd.Type != FromPcd.Type:
1096 EdkLogger.error("build", OPTION_CONFLICT, "Mismatched PCD type",
1097 ExtraData="%s.%s is defined as [%s] in module %s, but as [%s] in platform."\
1098 % (ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName,
1099 ToPcd.Type, Module, FromPcd.Type),
1100 File=self.MetaFile)
1101
1102 if FromPcd.MaxDatumSize not in [None, '']:
1103 ToPcd.MaxDatumSize = FromPcd.MaxDatumSize
1104 if FromPcd.DefaultValue not in [None, '']:
1105 ToPcd.DefaultValue = FromPcd.DefaultValue
1106 if FromPcd.TokenValue not in [None, '']:
1107 ToPcd.TokenValue = FromPcd.TokenValue
1108 if FromPcd.MaxDatumSize not in [None, '']:
1109 ToPcd.MaxDatumSize = FromPcd.MaxDatumSize
1110 if FromPcd.DatumType not in [None, '']:
1111 ToPcd.DatumType = FromPcd.DatumType
1112 if FromPcd.SkuInfoList not in [None, '', []]:
1113 ToPcd.SkuInfoList = FromPcd.SkuInfoList
1114
1115 # check the validation of datum
1116 IsValid, Cause = CheckPcdDatum(ToPcd.DatumType, ToPcd.DefaultValue)
1117 if not IsValid:
1118 EdkLogger.error('build', FORMAT_INVALID, Cause, File=self.MetaFile,
1119 ExtraData="%s.%s" % (ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName))
1120
1121 if ToPcd.DatumType == "VOID*" and ToPcd.MaxDatumSize in ['', None]:
1122 EdkLogger.debug(EdkLogger.DEBUG_9, "No MaxDatumSize specified for PCD %s.%s" \
1123 % (ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName))
1124 Value = ToPcd.DefaultValue
1125 if Value in [None, '']:
1126 ToPcd.MaxDatumSize = 1
1127 elif Value[0] == 'L':
1128 ToPcd.MaxDatumSize = str(len(Value) * 2)
1129 elif Value[0] == '{':
1130 ToPcd.MaxDatumSize = str(len(Value.split(',')))
1131 else:
1132 ToPcd.MaxDatumSize = str(len(Value))
1133
1134 # apply default SKU for dynamic PCDS if specified one is not available
1135 if (ToPcd.Type in PCD_DYNAMIC_TYPE_LIST or ToPcd.Type in PCD_DYNAMIC_EX_TYPE_LIST) \
1136 and ToPcd.SkuInfoList in [None, {}, '']:
1137 if self.Platform.SkuName in self.Platform.SkuIds:
1138 SkuName = self.Platform.SkuName
1139 else:
1140 SkuName = 'DEFAULT'
1141 ToPcd.SkuInfoList = {
1142 SkuName : SkuInfoClass(SkuName, self.Platform.SkuIds[SkuName], '', '', '', '', '', ToPcd.DefaultValue)
1143 }
1144
1145 ## Apply PCD setting defined platform to a module
1146 #
1147 # @param Module The module from which the PCD setting will be overrided
1148 #
1149 # @retval PCD_list The list PCDs with settings from platform
1150 #
1151 def ApplyPcdSetting(self, Module, Pcds):
1152 # for each PCD in module
1153 for Name,Guid in Pcds:
1154 PcdInModule = Pcds[Name,Guid]
1155 # find out the PCD setting in platform
1156 if (Name,Guid) in self.Platform.Pcds:
1157 PcdInPlatform = self.Platform.Pcds[Name,Guid]
1158 else:
1159 PcdInPlatform = None
1160 # then override the settings if any
1161 self._OverridePcd(PcdInModule, PcdInPlatform, Module)
1162 # resolve the VariableGuid value
1163 for SkuId in PcdInModule.SkuInfoList:
1164 Sku = PcdInModule.SkuInfoList[SkuId]
1165 if Sku.VariableGuid == '': continue
1166 Sku.VariableGuidValue = GuidValue(Sku.VariableGuid, self.PackageList)
1167 if Sku.VariableGuidValue == None:
1168 PackageList = "\n\t".join([str(P) for P in self.PackageList])
1169 EdkLogger.error(
1170 'build',
1171 RESOURCE_NOT_AVAILABLE,
1172 "Value of GUID [%s] is not found in" % Sku.VariableGuid,
1173 ExtraData=PackageList + "\n\t(used with %s.%s from module %s)" \
1174 % (Guid, Name, str(Module)),
1175 File=self.MetaFile
1176 )
1177
1178 # override PCD settings with module specific setting
1179 if Module in self.Platform.Modules:
1180 PlatformModule = self.Platform.Modules[str(Module)]
1181 for Key in PlatformModule.Pcds:
1182 if Key in Pcds:
1183 self._OverridePcd(Pcds[Key], PlatformModule.Pcds[Key], Module)
1184 return Pcds.values()
1185
1186 ## Resolve library names to library modules
1187 #
1188 # (for R8.x modules)
1189 #
1190 # @param Module The module from which the library names will be resolved
1191 #
1192 # @retval library_list The list of library modules
1193 #
1194 def ResolveLibraryReference(self, Module):
1195 EdkLogger.verbose("")
1196 EdkLogger.verbose("Library instances of module [%s] [%s]:" % (str(Module), self.Arch))
1197 LibraryConsumerList = [Module]
1198
1199 # "CompilerStub" is a must for R8 modules
1200 if Module.Libraries:
1201 Module.Libraries.append("CompilerStub")
1202 LibraryList = []
1203 while len(LibraryConsumerList) > 0:
1204 M = LibraryConsumerList.pop()
1205 for LibraryName in M.Libraries:
1206 Library = self.Platform.LibraryClasses[LibraryName, ':dummy:']
1207 if Library == None:
1208 for Key in self.Platform.LibraryClasses.data.keys():
1209 if LibraryName.upper() == Key.upper():
1210 Library = self.Platform.LibraryClasses[Key, ':dummy:']
1211 break
1212 if Library == None:
1213 EdkLogger.warn("build", "Library [%s] is not found" % LibraryName, File=str(M),
1214 ExtraData="\t%s [%s]" % (str(Module), self.Arch))
1215 continue
1216
1217 if Library not in LibraryList:
1218 LibraryList.append(Library)
1219 LibraryConsumerList.append(Library)
1220 EdkLogger.verbose("\t" + LibraryName + " : " + str(Library) + ' ' + str(type(Library)))
1221 return LibraryList
1222
1223 ## Expand * in build option key
1224 #
1225 # @param Options Options to be expanded
1226 #
1227 # @retval options Options expanded
1228 #
1229 def _ExpandBuildOption(self, Options, ModuleStyle=None):
1230 BuildOptions = {}
1231 FamilyMatch = False
1232 FamilyIsNull = True
1233 for Key in Options:
1234 if ModuleStyle != None and len (Key) > 2:
1235 # Check Module style is EDK or EDKII.
1236 # Only append build option for the matched style module.
1237 if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:
1238 continue
1239 elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:
1240 continue
1241 Family = Key[0]
1242 Target, Tag, Arch, Tool, Attr = Key[1].split("_")
1243 # if tool chain family doesn't match, skip it
1244 if Tool in self.ToolDefinition and Family != "":
1245 FamilyIsNull = False
1246 if self.ToolDefinition[Tool].get(TAB_TOD_DEFINES_BUILDRULEFAMILY, "") != "":
1247 if Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_BUILDRULEFAMILY]:
1248 continue
1249 elif Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_FAMILY]:
1250 continue
1251 FamilyMatch = True
1252 # expand any wildcard
1253 if Target == "*" or Target == self.BuildTarget:
1254 if Tag == "*" or Tag == self.ToolChain:
1255 if Arch == "*" or Arch == self.Arch:
1256 if Tool not in BuildOptions:
1257 BuildOptions[Tool] = {}
1258 if Attr != "FLAGS" or Attr not in BuildOptions[Tool]:
1259 BuildOptions[Tool][Attr] = Options[Key]
1260 else:
1261 # append options for the same tool
1262 BuildOptions[Tool][Attr] += " " + Options[Key]
1263 # Build Option Family has been checked, which need't to be checked again for family.
1264 if FamilyMatch or FamilyIsNull:
1265 return BuildOptions
1266
1267 for Key in Options:
1268 if ModuleStyle != None and len (Key) > 2:
1269 # Check Module style is EDK or EDKII.
1270 # Only append build option for the matched style module.
1271 if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:
1272 continue
1273 elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:
1274 continue
1275 Family = Key[0]
1276 Target, Tag, Arch, Tool, Attr = Key[1].split("_")
1277 # if tool chain family doesn't match, skip it
1278 if Tool not in self.ToolDefinition or Family =="":
1279 continue
1280 # option has been added before
1281 if Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_FAMILY]:
1282 continue
1283
1284 # expand any wildcard
1285 if Target == "*" or Target == self.BuildTarget:
1286 if Tag == "*" or Tag == self.ToolChain:
1287 if Arch == "*" or Arch == self.Arch:
1288 if Tool not in BuildOptions:
1289 BuildOptions[Tool] = {}
1290 if Attr != "FLAGS" or Attr not in BuildOptions[Tool]:
1291 BuildOptions[Tool][Attr] = Options[Key]
1292 else:
1293 # append options for the same tool
1294 BuildOptions[Tool][Attr] += " " + Options[Key]
1295 return BuildOptions
1296
1297 ## Append build options in platform to a module
1298 #
1299 # @param Module The module to which the build options will be appened
1300 #
1301 # @retval options The options appended with build options in platform
1302 #
1303 def ApplyBuildOption(self, Module):
1304 # Get the different options for the different style module
1305 if Module.AutoGenVersion < 0x00010005:
1306 PlatformOptions = self.EdkBuildOption
1307 else:
1308 PlatformOptions = self.EdkIIBuildOption
1309 ModuleOptions = self._ExpandBuildOption(Module.BuildOptions)
1310 if Module in self.Platform.Modules:
1311 PlatformModule = self.Platform.Modules[str(Module)]
1312 PlatformModuleOptions = self._ExpandBuildOption(PlatformModule.BuildOptions)
1313 else:
1314 PlatformModuleOptions = {}
1315
1316 AllTools = set(ModuleOptions.keys() + PlatformOptions.keys() + PlatformModuleOptions.keys() + self.ToolDefinition.keys())
1317 BuildOptions = {}
1318 for Tool in AllTools:
1319 if Tool not in BuildOptions:
1320 BuildOptions[Tool] = {}
1321
1322 for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, PlatformModuleOptions]:
1323 if Tool not in Options:
1324 continue
1325 for Attr in Options[Tool]:
1326 Value = Options[Tool][Attr]
1327 if Attr not in BuildOptions[Tool]:
1328 BuildOptions[Tool][Attr] = ""
1329 # check if override is indicated
1330 if Value.startswith('='):
1331 BuildOptions[Tool][Attr] = Value[1:]
1332 else:
1333 BuildOptions[Tool][Attr] += " " + Value
1334 if Module.AutoGenVersion < 0x00010005 and self.Workspace.UniFlag != None:
1335 #
1336 # Override UNI flag only for EDK module.
1337 #
1338 if 'BUILD' not in BuildOptions:
1339 BuildOptions['BUILD'] = {}
1340 BuildOptions['BUILD']['FLAGS'] = self.Workspace.UniFlag
1341 return BuildOptions
1342
1343 Platform = property(_GetPlatform)
1344 Name = property(_GetName)
1345 Guid = property(_GetGuid)
1346 Version = property(_GetVersion)
1347
1348 OutputDir = property(_GetOutputDir)
1349 BuildDir = property(_GetBuildDir)
1350 MakeFileDir = property(_GetMakeFileDir)
1351 FdfFile = property(_GetFdfFile)
1352
1353 PcdTokenNumber = property(_GetPcdTokenNumbers) # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
1354 DynamicPcdList = property(_GetDynamicPcdList) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1355 NonDynamicPcdList = property(_GetNonDynamicPcdList) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1356 PackageList = property(_GetPackageList)
1357
1358 ToolDefinition = property(_GetToolDefinition) # toolcode : tool path
1359 ToolDefinitionFile = property(_GetToolDefFile) # toolcode : lib path
1360 ToolChainFamily = property(_GetToolChainFamily)
1361 BuildRuleFamily = property(_GetBuildRuleFamily)
1362 BuildOption = property(_GetBuildOptions) # toolcode : option
1363 EdkBuildOption = property(_GetEdkBuildOptions) # edktoolcode : option
1364 EdkIIBuildOption = property(_GetEdkIIBuildOptions) # edkiitoolcode : option
1365
1366 BuildCommand = property(_GetBuildCommand)
1367 BuildRule = property(_GetBuildRule)
1368 ModuleAutoGenList = property(_GetModuleAutoGenList)
1369 LibraryAutoGenList = property(_GetLibraryAutoGenList)
1370
1371 ## ModuleAutoGen class
1372 #
1373 # This class encapsules the AutoGen behaviors for the build tools. In addition to
1374 # the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according
1375 # to the [depex] section in module's inf file.
1376 #
1377 class ModuleAutoGen(AutoGen):
1378 ## The real constructor of ModuleAutoGen
1379 #
1380 # This method is not supposed to be called by users of ModuleAutoGen. It's
1381 # only used by factory method __new__() to do real initialization work for an
1382 # object of ModuleAutoGen
1383 #
1384 # @param Workspace EdkIIWorkspaceBuild object
1385 # @param ModuleFile The path of module file
1386 # @param Target Build target (DEBUG, RELEASE)
1387 # @param Toolchain Name of tool chain
1388 # @param Arch The arch the module supports
1389 # @param PlatformFile Platform meta-file
1390 #
1391 def _Init(self, Workspace, ModuleFile, Target, Toolchain, Arch, PlatformFile):
1392 EdkLogger.debug(EdkLogger.DEBUG_9, "AutoGen module [%s] [%s]" % (ModuleFile, Arch))
1393 GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (ModuleFile, Arch, Toolchain, Target)
1394
1395 self.Workspace = Workspace
1396 self.WorkspaceDir = Workspace.WorkspaceDir
1397
1398 self.MetaFile = ModuleFile
1399 self.PlatformInfo = PlatformAutoGen(Workspace, PlatformFile, Target, Toolchain, Arch)
1400 # check if this module is employed by active platform
1401 if not self.PlatformInfo.ValidModule(self.MetaFile):
1402 EdkLogger.verbose("Module [%s] for [%s] is not employed by active platform\n" \
1403 % (self.MetaFile, Arch))
1404 return False
1405
1406 self.SourceDir = self.MetaFile.SubDir
1407 self.SourceOverrideDir = None
1408 # use overrided path defined in DSC file
1409 if self.MetaFile.Key in GlobalData.gOverrideDir:
1410 self.SourceOverrideDir = GlobalData.gOverrideDir[self.MetaFile.Key]
1411
1412 self.ToolChain = Toolchain
1413 self.BuildTarget = Target
1414 self.Arch = Arch
1415 self.ToolChainFamily = self.PlatformInfo.ToolChainFamily
1416 self.BuildRuleFamily = self.PlatformInfo.BuildRuleFamily
1417
1418 self.IsMakeFileCreated = False
1419 self.IsCodeFileCreated = False
1420
1421 self.BuildDatabase = self.Workspace.BuildDatabase
1422
1423 self._Module = None
1424 self._Name = None
1425 self._Guid = None
1426 self._Version = None
1427 self._ModuleType = None
1428 self._ComponentType = None
1429 self._PcdIsDriver = None
1430 self._AutoGenVersion = None
1431 self._LibraryFlag = None
1432 self._CustomMakefile = None
1433 self._Macro = None
1434
1435 self._BuildDir = None
1436 self._OutputDir = None
1437 self._DebugDir = None
1438 self._MakeFileDir = None
1439
1440 self._IncludePathList = None
1441 self._AutoGenFileList = None
1442 self._UnicodeFileList = None
1443 self._SourceFileList = None
1444 self._ObjectFileList = None
1445 self._BinaryFileList = None
1446
1447 self._DependentPackageList = None
1448 self._DependentLibraryList = None
1449 self._LibraryAutoGenList = None
1450 self._DerivedPackageList = None
1451 self._ModulePcdList = None
1452 self._LibraryPcdList = None
1453 self._GuidList = None
1454 self._ProtocolList = None
1455 self._PpiList = None
1456 self._DepexList = None
1457 self._DepexExpressionList = None
1458 self._BuildOption = None
1459 self._BuildTargets = None
1460 self._IntroBuildTargetList = None
1461 self._FinalBuildTargetList = None
1462 self._FileTypes = None
1463 self._BuildRules = None
1464
1465 return True
1466
1467 def __repr__(self):
1468 return "%s [%s]" % (self.MetaFile, self.Arch)
1469
1470 # Macros could be used in build_rule.txt (also Makefile)
1471 def _GetMacros(self):
1472 if self._Macro == None:
1473 self._Macro = sdict()
1474 self._Macro["WORKSPACE" ] = self.WorkspaceDir
1475 self._Macro["MODULE_NAME" ] = self.Name
1476 self._Macro["MODULE_GUID" ] = self.Guid
1477 self._Macro["MODULE_VERSION" ] = self.Version
1478 self._Macro["MODULE_TYPE" ] = self.ModuleType
1479 self._Macro["MODULE_FILE" ] = str(self.MetaFile)
1480 self._Macro["MODULE_FILE_BASE_NAME" ] = self.MetaFile.BaseName
1481 self._Macro["MODULE_RELATIVE_DIR" ] = self.SourceDir
1482 self._Macro["MODULE_DIR" ] = self.SourceDir
1483
1484 self._Macro["BASE_NAME" ] = self.Name
1485
1486 self._Macro["ARCH" ] = self.Arch
1487 self._Macro["TOOLCHAIN" ] = self.ToolChain
1488 self._Macro["TOOLCHAIN_TAG" ] = self.ToolChain
1489 self._Macro["TARGET" ] = self.BuildTarget
1490
1491 self._Macro["BUILD_DIR" ] = self.PlatformInfo.BuildDir
1492 self._Macro["BIN_DIR" ] = os.path.join(self.PlatformInfo.BuildDir, self.Arch)
1493 self._Macro["LIB_DIR" ] = os.path.join(self.PlatformInfo.BuildDir, self.Arch)
1494 self._Macro["MODULE_BUILD_DIR" ] = self.BuildDir
1495 self._Macro["OUTPUT_DIR" ] = self.OutputDir
1496 self._Macro["DEBUG_DIR" ] = self.DebugDir
1497 return self._Macro
1498
1499 ## Return the module build data object
1500 def _GetModule(self):
1501 if self._Module == None:
1502 self._Module = self.Workspace.BuildDatabase[self.MetaFile, self.Arch]
1503 return self._Module
1504
1505 ## Return the module name
1506 def _GetBaseName(self):
1507 return self.Module.BaseName
1508
1509 ## Return the module SourceOverridePath
1510 def _GetSourceOverridePath(self):
1511 return self.Module.SourceOverridePath
1512
1513 ## Return the module meta-file GUID
1514 def _GetGuid(self):
1515 return self.Module.Guid
1516
1517 ## Return the module version
1518 def _GetVersion(self):
1519 return self.Module.Version
1520
1521 ## Return the module type
1522 def _GetModuleType(self):
1523 return self.Module.ModuleType
1524
1525 ## Return the component type (for R8.x style of module)
1526 def _GetComponentType(self):
1527 return self.Module.ComponentType
1528
1529 ## Return the build type
1530 def _GetBuildType(self):
1531 return self.Module.BuildType
1532
1533 ## Return the PCD_IS_DRIVER setting
1534 def _GetPcdIsDriver(self):
1535 return self.Module.PcdIsDriver
1536
1537 ## Return the autogen version, i.e. module meta-file version
1538 def _GetAutoGenVersion(self):
1539 return self.Module.AutoGenVersion
1540
1541 ## Check if the module is library or not
1542 def _IsLibrary(self):
1543 if self._LibraryFlag == None:
1544 if self.Module.LibraryClass != None and self.Module.LibraryClass != []:
1545 self._LibraryFlag = True
1546 else:
1547 self._LibraryFlag = False
1548 return self._LibraryFlag
1549
1550 ## Return the directory to store intermediate files of the module
1551 def _GetBuildDir(self):
1552 if self._BuildDir == None:
1553 self._BuildDir = path.join(
1554 self.PlatformInfo.BuildDir,
1555 self.Arch,
1556 self.SourceDir,
1557 self.MetaFile.BaseName
1558 )
1559 CreateDirectory(self._BuildDir)
1560 return self._BuildDir
1561
1562 ## Return the directory to store the intermediate object files of the mdoule
1563 def _GetOutputDir(self):
1564 if self._OutputDir == None:
1565 self._OutputDir = path.join(self.BuildDir, "OUTPUT")
1566 CreateDirectory(self._OutputDir)
1567 return self._OutputDir
1568
1569 ## Return the directory to store auto-gened source files of the mdoule
1570 def _GetDebugDir(self):
1571 if self._DebugDir == None:
1572 self._DebugDir = path.join(self.BuildDir, "DEBUG")
1573 CreateDirectory(self._DebugDir)
1574 return self._DebugDir
1575
1576 ## Return the path of custom file
1577 def _GetCustomMakefile(self):
1578 if self._CustomMakefile == None:
1579 self._CustomMakefile = {}
1580 for Type in self.Module.CustomMakefile:
1581 if Type in gMakeTypeMap:
1582 MakeType = gMakeTypeMap[Type]
1583 else:
1584 MakeType = 'nmake'
1585 if self.SourceOverrideDir != None:
1586 File = os.path.join(self.SourceOverrideDir, self.Module.CustomMakefile[Type])
1587 if not os.path.exists(File):
1588 File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])
1589 else:
1590 File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])
1591 self._CustomMakefile[MakeType] = File
1592 return self._CustomMakefile
1593
1594 ## Return the directory of the makefile
1595 #
1596 # @retval string The directory string of module's makefile
1597 #
1598 def _GetMakeFileDir(self):
1599 return self.BuildDir
1600
1601 ## Return build command string
1602 #
1603 # @retval string Build command string
1604 #
1605 def _GetBuildCommand(self):
1606 return self.PlatformInfo.BuildCommand
1607
1608 ## Get object list of all packages the module and its dependent libraries belong to
1609 #
1610 # @retval list The list of package object
1611 #
1612 def _GetDerivedPackageList(self):
1613 PackageList = []
1614 for M in [self.Module] + self.DependentLibraryList:
1615 for Package in M.Packages:
1616 if Package in PackageList:
1617 continue
1618 PackageList.append(Package)
1619 return PackageList
1620
1621 ## Merge dependency expression
1622 #
1623 # @retval list The token list of the dependency expression after parsed
1624 #
1625 def _GetDepexTokenList(self):
1626 if self._DepexList == None:
1627 self._DepexList = {}
1628 if self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:
1629 return self._DepexList
1630
1631 self._DepexList[self.ModuleType] = []
1632
1633 for ModuleType in self._DepexList:
1634 DepexList = self._DepexList[ModuleType]
1635 #
1636 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
1637 #
1638 for M in [self.Module] + self.DependentLibraryList:
1639 Inherited = False
1640 for D in M.Depex[self.Arch, ModuleType]:
1641 if DepexList != []:
1642 DepexList.append('AND')
1643 DepexList.append('(')
1644 DepexList.extend(D)
1645 if DepexList[-1] == 'END': # no need of a END at this time
1646 DepexList.pop()
1647 DepexList.append(')')
1648 Inherited = True
1649 if Inherited:
1650 EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexList))
1651 if 'BEFORE' in DepexList or 'AFTER' in DepexList:
1652 break
1653 if len(DepexList) > 0:
1654 EdkLogger.verbose('')
1655 return self._DepexList
1656
1657 ## Merge dependency expression
1658 #
1659 # @retval list The token list of the dependency expression after parsed
1660 #
1661 def _GetDepexExpressionTokenList(self):
1662 if self._DepexExpressionList == None:
1663 self._DepexExpressionList = {}
1664 if self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:
1665 return self._DepexExpressionList
1666
1667 self._DepexExpressionList[self.ModuleType] = ''
1668
1669 for ModuleType in self._DepexExpressionList:
1670 DepexExpressionList = self._DepexExpressionList[ModuleType]
1671 #
1672 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
1673 #
1674 for M in [self.Module] + self.DependentLibraryList:
1675 Inherited = False
1676 for D in M.DepexExpression[self.Arch, ModuleType]:
1677 if DepexExpressionList != '':
1678 DepexExpressionList += ' AND '
1679 DepexExpressionList += '('
1680 DepexExpressionList += D
1681 DepexExpressionList = DepexExpressionList.rstrip('END').strip()
1682 DepexExpressionList += ')'
1683 Inherited = True
1684 if Inherited:
1685 EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexExpressionList))
1686 if 'BEFORE' in DepexExpressionList or 'AFTER' in DepexExpressionList:
1687 break
1688 if len(DepexExpressionList) > 0:
1689 EdkLogger.verbose('')
1690 self._DepexExpressionList[ModuleType] = DepexExpressionList
1691 return self._DepexExpressionList
1692
1693 ## Return the list of specification version required for the module
1694 #
1695 # @retval list The list of specification defined in module file
1696 #
1697 def _GetSpecification(self):
1698 return self.Module.Specification
1699
1700 ## Tool option for the module build
1701 #
1702 # @param PlatformInfo The object of PlatformBuildInfo
1703 # @retval dict The dict containing valid options
1704 #
1705 def _GetModuleBuildOption(self):
1706 if self._BuildOption == None:
1707 self._BuildOption = self.PlatformInfo.ApplyBuildOption(self.Module)
1708 return self._BuildOption
1709
1710 ## Return a list of files which can be built from source
1711 #
1712 # What kind of files can be built is determined by build rules in
1713 # $(WORKSPACE)/Conf/build_rule.txt and toolchain family.
1714 #
1715 def _GetSourceFileList(self):
1716 if self._SourceFileList == None:
1717 self._SourceFileList = []
1718 for F in self.Module.Sources:
1719 # match tool chain
1720 if F.TagName not in ("", "*", self.ToolChain):
1721 EdkLogger.debug(EdkLogger.DEBUG_9, "The toolchain [%s] for processing file [%s] is found, "
1722 "but [%s] is needed" % (F.TagName, str(F), self.ToolChain))
1723 continue
1724 # match tool chain family
1725 if F.ToolChainFamily not in ("", "*", self.ToolChainFamily):
1726 EdkLogger.debug(
1727 EdkLogger.DEBUG_0,
1728 "The file [%s] must be built by tools of [%s], " \
1729 "but current toolchain family is [%s]" \
1730 % (str(F), F.ToolChainFamily, self.ToolChainFamily))
1731 continue
1732
1733 # add the file path into search path list for file including
1734 if F.Dir not in self.IncludePathList and self.AutoGenVersion >= 0x00010005:
1735 self.IncludePathList.insert(0, F.Dir)
1736 self._SourceFileList.append(F)
1737 self._ApplyBuildRule(F, TAB_UNKNOWN_FILE)
1738 return self._SourceFileList
1739
1740 ## Return the list of unicode files
1741 def _GetUnicodeFileList(self):
1742 if self._UnicodeFileList == None:
1743 if TAB_UNICODE_FILE in self.FileTypes:
1744 self._UnicodeFileList = self.FileTypes[TAB_UNICODE_FILE]
1745 else:
1746 self._UnicodeFileList = []
1747 return self._UnicodeFileList
1748
1749 ## Return a list of files which can be built from binary
1750 #
1751 # "Build" binary files are just to copy them to build directory.
1752 #
1753 # @retval list The list of files which can be built later
1754 #
1755 def _GetBinaryFiles(self):
1756 if self._BinaryFileList == None:
1757 self._BinaryFileList = []
1758 for F in self.Module.Binaries:
1759 if F.Target not in ['COMMON', '*'] and F.Target != self.BuildTarget:
1760 continue
1761 self._BinaryFileList.append(F)
1762 self._ApplyBuildRule(F, F.Type)
1763 return self._BinaryFileList
1764
1765 def _GetBuildRules(self):
1766 if self._BuildRules == None:
1767 BuildRules = {}
1768 BuildRuleDatabase = self.PlatformInfo.BuildRule
1769 for Type in BuildRuleDatabase.FileTypeList:
1770 #first try getting build rule by BuildRuleFamily
1771 RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.BuildRuleFamily]
1772 if not RuleObject:
1773 # build type is always module type, but ...
1774 if self.ModuleType != self.BuildType:
1775 RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.BuildRuleFamily]
1776 #second try getting build rule by ToolChainFamily
1777 if not RuleObject:
1778 RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.ToolChainFamily]
1779 if not RuleObject:
1780 # build type is always module type, but ...
1781 if self.ModuleType != self.BuildType:
1782 RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.ToolChainFamily]
1783 if not RuleObject:
1784 continue
1785 RuleObject = RuleObject.Instantiate(self.Macros)
1786 BuildRules[Type] = RuleObject
1787 for Ext in RuleObject.SourceFileExtList:
1788 BuildRules[Ext] = RuleObject
1789 self._BuildRules = BuildRules
1790 return self._BuildRules
1791
1792 def _ApplyBuildRule(self, File, FileType):
1793 if self._BuildTargets == None:
1794 self._IntroBuildTargetList = set()
1795 self._FinalBuildTargetList = set()
1796 self._BuildTargets = {}
1797 self._FileTypes = {}
1798
1799 LastTarget = None
1800 RuleChain = []
1801 SourceList = [File]
1802 Index = 0
1803 while Index < len(SourceList):
1804 Source = SourceList[Index]
1805 Index = Index + 1
1806
1807 if Source != File:
1808 CreateDirectory(Source.Dir)
1809
1810 if File.IsBinary and File == Source and self._BinaryFileList != None and File in self._BinaryFileList:
1811 RuleObject = self.BuildRules[TAB_DEFAULT_BINARY_FILE]
1812 elif FileType in self.BuildRules:
1813 RuleObject = self.BuildRules[FileType]
1814 elif Source.Ext in self.BuildRules:
1815 RuleObject = self.BuildRules[Source.Ext]
1816 else:
1817 # stop at no more rules
1818 if LastTarget:
1819 self._FinalBuildTargetList.add(LastTarget)
1820 break
1821
1822 FileType = RuleObject.SourceFileType
1823 if FileType not in self._FileTypes:
1824 self._FileTypes[FileType] = set()
1825 self._FileTypes[FileType].add(Source)
1826
1827 # stop at STATIC_LIBRARY for library
1828 if self.IsLibrary and FileType == TAB_STATIC_LIBRARY:
1829 if LastTarget:
1830 self._FinalBuildTargetList.add(LastTarget)
1831 break
1832
1833 Target = RuleObject.Apply(Source)
1834 if not Target:
1835 if LastTarget:
1836 self._FinalBuildTargetList.add(LastTarget)
1837 break
1838 elif not Target.Outputs:
1839 # Only do build for target with outputs
1840 self._FinalBuildTargetList.add(Target)
1841
1842 if FileType not in self._BuildTargets:
1843 self._BuildTargets[FileType] = set()
1844 self._BuildTargets[FileType].add(Target)
1845
1846 if not Source.IsBinary and Source == File:
1847 self._IntroBuildTargetList.add(Target)
1848
1849 # to avoid cyclic rule
1850 if FileType in RuleChain:
1851 break
1852
1853 RuleChain.append(FileType)
1854 SourceList.extend(Target.Outputs)
1855 LastTarget = Target
1856 FileType = TAB_UNKNOWN_FILE
1857
1858 def _GetTargets(self):
1859 if self._BuildTargets == None:
1860 self._IntroBuildTargetList = set()
1861 self._FinalBuildTargetList = set()
1862 self._BuildTargets = {}
1863 self._FileTypes = {}
1864
1865 #TRICK: call _GetSourceFileList to apply build rule for binary files
1866 if self.SourceFileList:
1867 pass
1868
1869 #TRICK: call _GetBinaryFileList to apply build rule for binary files
1870 if self.BinaryFileList:
1871 pass
1872
1873 return self._BuildTargets
1874
1875 def _GetIntroTargetList(self):
1876 self._GetTargets()
1877 return self._IntroBuildTargetList
1878
1879 def _GetFinalTargetList(self):
1880 self._GetTargets()
1881 return self._FinalBuildTargetList
1882
1883 def _GetFileTypes(self):
1884 self._GetTargets()
1885 return self._FileTypes
1886
1887 ## Get the list of package object the module depends on
1888 #
1889 # @retval list The package object list
1890 #
1891 def _GetDependentPackageList(self):
1892 return self.Module.Packages
1893
1894 ## Return the list of auto-generated code file
1895 #
1896 # @retval list The list of auto-generated file
1897 #
1898 def _GetAutoGenFileList(self):
1899 UniStringAutoGenC = True
1900 UniStringBinBuffer = None
1901 if self.BuildType == 'UEFI_HII':
1902 UniStringBinBuffer = StringIO()
1903 UniStringAutoGenC = False
1904 if self._AutoGenFileList == None:
1905 self._AutoGenFileList = {}
1906 AutoGenC = TemplateString()
1907 AutoGenH = TemplateString()
1908 StringH = TemplateString()
1909 GenC.CreateCode(self, AutoGenC, AutoGenH, StringH, UniStringAutoGenC, UniStringBinBuffer)
1910 if str(AutoGenC) != "" and TAB_C_CODE_FILE in self.FileTypes:
1911 AutoFile = PathClass(gAutoGenCodeFileName, self.DebugDir)
1912 self._AutoGenFileList[AutoFile] = str(AutoGenC)
1913 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
1914 if str(AutoGenH) != "":
1915 AutoFile = PathClass(gAutoGenHeaderFileName, self.DebugDir)
1916 self._AutoGenFileList[AutoFile] = str(AutoGenH)
1917 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
1918 if str(StringH) != "":
1919 AutoFile = PathClass(gAutoGenStringFileName % {"module_name":self.Name}, self.DebugDir)
1920 self._AutoGenFileList[AutoFile] = str(StringH)
1921 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
1922 if UniStringBinBuffer != None and UniStringBinBuffer.getvalue() != "":
1923 AutoFile = PathClass(gAutoGenStringFormFileName % {"module_name":self.Name}, self.OutputDir)
1924 self._AutoGenFileList[AutoFile] = UniStringBinBuffer.getvalue()
1925 AutoFile.IsBinary = True
1926 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
1927 if UniStringBinBuffer != None:
1928 UniStringBinBuffer.close()
1929 return self._AutoGenFileList
1930
1931 ## Return the list of library modules explicitly or implicityly used by this module
1932 def _GetLibraryList(self):
1933 if self._DependentLibraryList == None:
1934 # only merge library classes and PCD for non-library module
1935 if self.IsLibrary:
1936 self._DependentLibraryList = []
1937 else:
1938 if self.AutoGenVersion < 0x00010005:
1939 self._DependentLibraryList = self.PlatformInfo.ResolveLibraryReference(self.Module)
1940 else:
1941 self._DependentLibraryList = self.PlatformInfo.ApplyLibraryInstance(self.Module)
1942 return self._DependentLibraryList
1943
1944 ## Get the list of PCDs from current module
1945 #
1946 # @retval list The list of PCD
1947 #
1948 def _GetModulePcdList(self):
1949 if self._ModulePcdList == None:
1950 # apply PCD settings from platform
1951 self._ModulePcdList = self.PlatformInfo.ApplyPcdSetting(self.Module, self.Module.Pcds)
1952 return self._ModulePcdList
1953
1954 ## Get the list of PCDs from dependent libraries
1955 #
1956 # @retval list The list of PCD
1957 #
1958 def _GetLibraryPcdList(self):
1959 if self._LibraryPcdList == None:
1960 Pcds = {}
1961 if not self.IsLibrary:
1962 # get PCDs from dependent libraries
1963 for Library in self.DependentLibraryList:
1964 for Key in Library.Pcds:
1965 # skip duplicated PCDs
1966 if Key in self.Module.Pcds or Key in Pcds:
1967 continue
1968 Pcds[Key] = copy.copy(Library.Pcds[Key])
1969 # apply PCD settings from platform
1970 self._LibraryPcdList = self.PlatformInfo.ApplyPcdSetting(self.Module, Pcds)
1971 else:
1972 self._LibraryPcdList = []
1973 return self._LibraryPcdList
1974
1975 ## Get the GUID value mapping
1976 #
1977 # @retval dict The mapping between GUID cname and its value
1978 #
1979 def _GetGuidList(self):
1980 if self._GuidList == None:
1981 self._GuidList = self.Module.Guids
1982 for Library in self.DependentLibraryList:
1983 self._GuidList.update(Library.Guids)
1984 return self._GuidList
1985
1986 ## Get the protocol value mapping
1987 #
1988 # @retval dict The mapping between protocol cname and its value
1989 #
1990 def _GetProtocolList(self):
1991 if self._ProtocolList == None:
1992 self._ProtocolList = self.Module.Protocols
1993 for Library in self.DependentLibraryList:
1994 self._ProtocolList.update(Library.Protocols)
1995 return self._ProtocolList
1996
1997 ## Get the PPI value mapping
1998 #
1999 # @retval dict The mapping between PPI cname and its value
2000 #
2001 def _GetPpiList(self):
2002 if self._PpiList == None:
2003 self._PpiList = self.Module.Ppis
2004 for Library in self.DependentLibraryList:
2005 self._PpiList.update(Library.Ppis)
2006 return self._PpiList
2007
2008 ## Get the list of include search path
2009 #
2010 # @retval list The list path
2011 #
2012 def _GetIncludePathList(self):
2013 if self._IncludePathList == None:
2014 self._IncludePathList = []
2015 if self.AutoGenVersion < 0x00010005:
2016 for Inc in self.Module.Includes:
2017 if Inc not in self._IncludePathList:
2018 self._IncludePathList.append(Inc)
2019 # for r8 modules
2020 Inc = path.join(Inc, self.Arch.capitalize())
2021 if os.path.exists(Inc) and Inc not in self._IncludePathList:
2022 self._IncludePathList.append(Inc)
2023 # r8 module needs to put DEBUG_DIR at the end of search path and not to use SOURCE_DIR all the time
2024 self._IncludePathList.append(self.DebugDir)
2025 else:
2026 self._IncludePathList.append(self.MetaFile.Dir)
2027 self._IncludePathList.append(self.DebugDir)
2028
2029 for Package in self.Module.Packages:
2030 PackageDir = path.join(self.WorkspaceDir, Package.MetaFile.Dir)
2031 if PackageDir not in self._IncludePathList:
2032 self._IncludePathList.append(PackageDir)
2033 for Inc in Package.Includes:
2034 if Inc not in self._IncludePathList:
2035 self._IncludePathList.append(str(Inc))
2036 return self._IncludePathList
2037
2038 ## Create makefile for the module and its dependent libraries
2039 #
2040 # @param CreateLibraryMakeFile Flag indicating if or not the makefiles of
2041 # dependent libraries will be created
2042 #
2043 def CreateMakeFile(self, CreateLibraryMakeFile=True):
2044 if self.IsMakeFileCreated:
2045 return
2046
2047 if not self.IsLibrary and CreateLibraryMakeFile:
2048 for LibraryAutoGen in self.LibraryAutoGenList:
2049 LibraryAutoGen.CreateMakeFile()
2050
2051 if len(self.CustomMakefile) == 0:
2052 Makefile = GenMake.ModuleMakefile(self)
2053 else:
2054 Makefile = GenMake.CustomMakefile(self)
2055 if Makefile.Generate():
2056 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated makefile for module %s [%s]" %
2057 (self.Name, self.Arch))
2058 else:
2059 EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of makefile for module %s [%s]" %
2060 (self.Name, self.Arch))
2061
2062 self.IsMakeFileCreated = True
2063
2064 ## Create autogen code for the module and its dependent libraries
2065 #
2066 # @param CreateLibraryCodeFile Flag indicating if or not the code of
2067 # dependent libraries will be created
2068 #
2069 def CreateCodeFile(self, CreateLibraryCodeFile=True):
2070 if self.IsCodeFileCreated:
2071 return
2072
2073 if not self.IsLibrary and CreateLibraryCodeFile:
2074 for LibraryAutoGen in self.LibraryAutoGenList:
2075 LibraryAutoGen.CreateCodeFile()
2076
2077 AutoGenList = []
2078 IgoredAutoGenList = []
2079
2080 for File in self.AutoGenFileList:
2081 if GenC.Generate(File.Path, self.AutoGenFileList[File], File.IsBinary):
2082 #Ignore R8 AutoGen.c
2083 if self.AutoGenVersion < 0x00010005 and File.Name == 'AutoGen.c':
2084 continue
2085
2086 AutoGenList.append(str(File))
2087 else:
2088 IgoredAutoGenList.append(str(File))
2089
2090 # Skip the following code for EDK I inf
2091 if self.AutoGenVersion < 0x00010005:
2092 return
2093
2094 for ModuleType in self.DepexList:
2095 # Ignore empty [depex] section or [depex] section for "USER_DEFINED" module
2096 if len(self.DepexList[ModuleType]) == 0 or ModuleType == "USER_DEFINED":
2097 continue
2098
2099 Dpx = GenDepex.DependencyExpression(self.DepexList[ModuleType], ModuleType, True)
2100 DpxFile = gAutoGenDepexFileName % {"module_name" : self.Name}
2101
2102 if Dpx.Generate(path.join(self.OutputDir, DpxFile)):
2103 AutoGenList.append(str(DpxFile))
2104 else:
2105 IgoredAutoGenList.append(str(DpxFile))
2106
2107 if IgoredAutoGenList == []:
2108 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated [%s] files for module %s [%s]" %
2109 (" ".join(AutoGenList), self.Name, self.Arch))
2110 elif AutoGenList == []:
2111 EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of [%s] files for module %s [%s]" %
2112 (" ".join(IgoredAutoGenList), self.Name, self.Arch))
2113 else:
2114 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated [%s] (skipped %s) files for module %s [%s]" %
2115 (" ".join(AutoGenList), " ".join(IgoredAutoGenList), self.Name, self.Arch))
2116
2117 self.IsCodeFileCreated = True
2118 return AutoGenList
2119
2120 ## Summarize the ModuleAutoGen objects of all libraries used by this module
2121 def _GetLibraryAutoGenList(self):
2122 if self._LibraryAutoGenList == None:
2123 self._LibraryAutoGenList = []
2124 for Library in self.DependentLibraryList:
2125 La = ModuleAutoGen(
2126 self.Workspace,
2127 Library.MetaFile,
2128 self.BuildTarget,
2129 self.ToolChain,
2130 self.Arch,
2131 self.PlatformInfo.MetaFile
2132 )
2133 if La not in self._LibraryAutoGenList:
2134 self._LibraryAutoGenList.append(La)
2135 for Lib in La.CodaTargetList:
2136 self._ApplyBuildRule(Lib.Target, TAB_UNKNOWN_FILE)
2137 return self._LibraryAutoGenList
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