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