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