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