]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/AutoGen/AutoGen.py
ff1c4fd82c362ab6d72341bf7a9e596250042128
[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 if len(self.BuildDatabase.WorkspaceDb.PackageList) >= 1:
361 for Package in self.BuildDatabase.WorkspaceDb.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 # R9 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 R8.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 R8 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 SourceOverridePath
1798 def _GetSourceOverridePath(self):
1799 return self.Module.SourceOverridePath
1800
1801 ## Return the module meta-file GUID
1802 def _GetGuid(self):
1803 return self.Module.Guid
1804
1805 ## Return the module version
1806 def _GetVersion(self):
1807 return self.Module.Version
1808
1809 ## Return the module type
1810 def _GetModuleType(self):
1811 return self.Module.ModuleType
1812
1813 ## Return the component type (for R8.x style of module)
1814 def _GetComponentType(self):
1815 return self.Module.ComponentType
1816
1817 ## Return the build type
1818 def _GetBuildType(self):
1819 return self.Module.BuildType
1820
1821 ## Return the PCD_IS_DRIVER setting
1822 def _GetPcdIsDriver(self):
1823 return self.Module.PcdIsDriver
1824
1825 ## Return the autogen version, i.e. module meta-file version
1826 def _GetAutoGenVersion(self):
1827 return self.Module.AutoGenVersion
1828
1829 ## Check if the module is library or not
1830 def _IsLibrary(self):
1831 if self._LibraryFlag == None:
1832 if self.Module.LibraryClass != None and self.Module.LibraryClass != []:
1833 self._LibraryFlag = True
1834 else:
1835 self._LibraryFlag = False
1836 return self._LibraryFlag
1837
1838 ## Return the directory to store intermediate files of the module
1839 def _GetBuildDir(self):
1840 if self._BuildDir == None:
1841 self._BuildDir = path.join(
1842 self.PlatformInfo.BuildDir,
1843 self.Arch,
1844 self.SourceDir,
1845 self.MetaFile.BaseName
1846 )
1847 CreateDirectory(self._BuildDir)
1848 return self._BuildDir
1849
1850 ## Return the directory to store the intermediate object files of the mdoule
1851 def _GetOutputDir(self):
1852 if self._OutputDir == None:
1853 self._OutputDir = path.join(self.BuildDir, "OUTPUT")
1854 CreateDirectory(self._OutputDir)
1855 return self._OutputDir
1856
1857 ## Return the directory to store auto-gened source files of the mdoule
1858 def _GetDebugDir(self):
1859 if self._DebugDir == None:
1860 self._DebugDir = path.join(self.BuildDir, "DEBUG")
1861 CreateDirectory(self._DebugDir)
1862 return self._DebugDir
1863
1864 ## Return the path of custom file
1865 def _GetCustomMakefile(self):
1866 if self._CustomMakefile == None:
1867 self._CustomMakefile = {}
1868 for Type in self.Module.CustomMakefile:
1869 if Type in gMakeTypeMap:
1870 MakeType = gMakeTypeMap[Type]
1871 else:
1872 MakeType = 'nmake'
1873 if self.SourceOverrideDir != None:
1874 File = os.path.join(self.SourceOverrideDir, self.Module.CustomMakefile[Type])
1875 if not os.path.exists(File):
1876 File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])
1877 else:
1878 File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])
1879 self._CustomMakefile[MakeType] = File
1880 return self._CustomMakefile
1881
1882 ## Return the directory of the makefile
1883 #
1884 # @retval string The directory string of module's makefile
1885 #
1886 def _GetMakeFileDir(self):
1887 return self.BuildDir
1888
1889 ## Return build command string
1890 #
1891 # @retval string Build command string
1892 #
1893 def _GetBuildCommand(self):
1894 return self.PlatformInfo.BuildCommand
1895
1896 ## Get object list of all packages the module and its dependent libraries belong to
1897 #
1898 # @retval list The list of package object
1899 #
1900 def _GetDerivedPackageList(self):
1901 PackageList = []
1902 for M in [self.Module] + self.DependentLibraryList:
1903 for Package in M.Packages:
1904 if Package in PackageList:
1905 continue
1906 PackageList.append(Package)
1907 return PackageList
1908
1909 ## Merge dependency expression
1910 #
1911 # @retval list The token list of the dependency expression after parsed
1912 #
1913 def _GetDepexTokenList(self):
1914 if self._DepexList == None:
1915 self._DepexList = {}
1916 if self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:
1917 return self._DepexList
1918
1919 self._DepexList[self.ModuleType] = []
1920
1921 for ModuleType in self._DepexList:
1922 DepexList = self._DepexList[ModuleType]
1923 #
1924 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
1925 #
1926 for M in [self.Module] + self.DependentLibraryList:
1927 Inherited = False
1928 for D in M.Depex[self.Arch, ModuleType]:
1929 if DepexList != []:
1930 DepexList.append('AND')
1931 DepexList.append('(')
1932 DepexList.extend(D)
1933 if DepexList[-1] == 'END': # no need of a END at this time
1934 DepexList.pop()
1935 DepexList.append(')')
1936 Inherited = True
1937 if Inherited:
1938 EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexList))
1939 if 'BEFORE' in DepexList or 'AFTER' in DepexList:
1940 break
1941 if len(DepexList) > 0:
1942 EdkLogger.verbose('')
1943 return self._DepexList
1944
1945 ## Merge dependency expression
1946 #
1947 # @retval list The token list of the dependency expression after parsed
1948 #
1949 def _GetDepexExpressionTokenList(self):
1950 if self._DepexExpressionList == None:
1951 self._DepexExpressionList = {}
1952 if self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:
1953 return self._DepexExpressionList
1954
1955 self._DepexExpressionList[self.ModuleType] = ''
1956
1957 for ModuleType in self._DepexExpressionList:
1958 DepexExpressionList = self._DepexExpressionList[ModuleType]
1959 #
1960 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
1961 #
1962 for M in [self.Module] + self.DependentLibraryList:
1963 Inherited = False
1964 for D in M.DepexExpression[self.Arch, ModuleType]:
1965 if DepexExpressionList != '':
1966 DepexExpressionList += ' AND '
1967 DepexExpressionList += '('
1968 DepexExpressionList += D
1969 DepexExpressionList = DepexExpressionList.rstrip('END').strip()
1970 DepexExpressionList += ')'
1971 Inherited = True
1972 if Inherited:
1973 EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexExpressionList))
1974 if 'BEFORE' in DepexExpressionList or 'AFTER' in DepexExpressionList:
1975 break
1976 if len(DepexExpressionList) > 0:
1977 EdkLogger.verbose('')
1978 self._DepexExpressionList[ModuleType] = DepexExpressionList
1979 return self._DepexExpressionList
1980
1981 ## Return the list of specification version required for the module
1982 #
1983 # @retval list The list of specification defined in module file
1984 #
1985 def _GetSpecification(self):
1986 return self.Module.Specification
1987
1988 ## Tool option for the module build
1989 #
1990 # @param PlatformInfo The object of PlatformBuildInfo
1991 # @retval dict The dict containing valid options
1992 #
1993 def _GetModuleBuildOption(self):
1994 if self._BuildOption == None:
1995 self._BuildOption = self.PlatformInfo.ApplyBuildOption(self.Module)
1996 return self._BuildOption
1997
1998 ## Return a list of files which can be built from source
1999 #
2000 # What kind of files can be built is determined by build rules in
2001 # $(WORKSPACE)/Conf/build_rule.txt and toolchain family.
2002 #
2003 def _GetSourceFileList(self):
2004 if self._SourceFileList == None:
2005 self._SourceFileList = []
2006 for F in self.Module.Sources:
2007 # match tool chain
2008 if F.TagName not in ("", "*", self.ToolChain):
2009 EdkLogger.debug(EdkLogger.DEBUG_9, "The toolchain [%s] for processing file [%s] is found, "
2010 "but [%s] is needed" % (F.TagName, str(F), self.ToolChain))
2011 continue
2012 # match tool chain family
2013 if F.ToolChainFamily not in ("", "*", self.ToolChainFamily):
2014 EdkLogger.debug(
2015 EdkLogger.DEBUG_0,
2016 "The file [%s] must be built by tools of [%s], " \
2017 "but current toolchain family is [%s]" \
2018 % (str(F), F.ToolChainFamily, self.ToolChainFamily))
2019 continue
2020
2021 # add the file path into search path list for file including
2022 if F.Dir not in self.IncludePathList and self.AutoGenVersion >= 0x00010005:
2023 self.IncludePathList.insert(0, F.Dir)
2024 self._SourceFileList.append(F)
2025 self._ApplyBuildRule(F, TAB_UNKNOWN_FILE)
2026 return self._SourceFileList
2027
2028 ## Return the list of unicode files
2029 def _GetUnicodeFileList(self):
2030 if self._UnicodeFileList == None:
2031 if TAB_UNICODE_FILE in self.FileTypes:
2032 self._UnicodeFileList = self.FileTypes[TAB_UNICODE_FILE]
2033 else:
2034 self._UnicodeFileList = []
2035 return self._UnicodeFileList
2036
2037 ## Return a list of files which can be built from binary
2038 #
2039 # "Build" binary files are just to copy them to build directory.
2040 #
2041 # @retval list The list of files which can be built later
2042 #
2043 def _GetBinaryFiles(self):
2044 if self._BinaryFileList == None:
2045 self._BinaryFileList = []
2046 for F in self.Module.Binaries:
2047 if F.Target not in ['COMMON', '*'] and F.Target != self.BuildTarget:
2048 continue
2049 self._BinaryFileList.append(F)
2050 self._ApplyBuildRule(F, F.Type)
2051 return self._BinaryFileList
2052
2053 def _GetBuildRules(self):
2054 if self._BuildRules == None:
2055 BuildRules = {}
2056 BuildRuleDatabase = self.PlatformInfo.BuildRule
2057 for Type in BuildRuleDatabase.FileTypeList:
2058 #first try getting build rule by BuildRuleFamily
2059 RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.BuildRuleFamily]
2060 if not RuleObject:
2061 # build type is always module type, but ...
2062 if self.ModuleType != self.BuildType:
2063 RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.BuildRuleFamily]
2064 #second try getting build rule by ToolChainFamily
2065 if not RuleObject:
2066 RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.ToolChainFamily]
2067 if not RuleObject:
2068 # build type is always module type, but ...
2069 if self.ModuleType != self.BuildType:
2070 RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.ToolChainFamily]
2071 if not RuleObject:
2072 continue
2073 RuleObject = RuleObject.Instantiate(self.Macros)
2074 BuildRules[Type] = RuleObject
2075 for Ext in RuleObject.SourceFileExtList:
2076 BuildRules[Ext] = RuleObject
2077 self._BuildRules = BuildRules
2078 return self._BuildRules
2079
2080 def _ApplyBuildRule(self, File, FileType):
2081 if self._BuildTargets == None:
2082 self._IntroBuildTargetList = set()
2083 self._FinalBuildTargetList = set()
2084 self._BuildTargets = {}
2085 self._FileTypes = {}
2086
2087 LastTarget = None
2088 RuleChain = []
2089 SourceList = [File]
2090 Index = 0
2091 while Index < len(SourceList):
2092 Source = SourceList[Index]
2093 Index = Index + 1
2094
2095 if Source != File:
2096 CreateDirectory(Source.Dir)
2097
2098 if File.IsBinary and File == Source and self._BinaryFileList != None and File in self._BinaryFileList:
2099 # Skip all files that are not binary libraries
2100 if not self.IsLibrary:
2101 continue
2102 RuleObject = self.BuildRules[TAB_DEFAULT_BINARY_FILE]
2103 elif FileType in self.BuildRules:
2104 RuleObject = self.BuildRules[FileType]
2105 elif Source.Ext in self.BuildRules:
2106 RuleObject = self.BuildRules[Source.Ext]
2107 else:
2108 # stop at no more rules
2109 if LastTarget:
2110 self._FinalBuildTargetList.add(LastTarget)
2111 break
2112
2113 FileType = RuleObject.SourceFileType
2114 if FileType not in self._FileTypes:
2115 self._FileTypes[FileType] = set()
2116 self._FileTypes[FileType].add(Source)
2117
2118 # stop at STATIC_LIBRARY for library
2119 if self.IsLibrary and FileType == TAB_STATIC_LIBRARY:
2120 if LastTarget:
2121 self._FinalBuildTargetList.add(LastTarget)
2122 break
2123
2124 Target = RuleObject.Apply(Source)
2125 if not Target:
2126 if LastTarget:
2127 self._FinalBuildTargetList.add(LastTarget)
2128 break
2129 elif not Target.Outputs:
2130 # Only do build for target with outputs
2131 self._FinalBuildTargetList.add(Target)
2132
2133 if FileType not in self._BuildTargets:
2134 self._BuildTargets[FileType] = set()
2135 self._BuildTargets[FileType].add(Target)
2136
2137 if not Source.IsBinary and Source == File:
2138 self._IntroBuildTargetList.add(Target)
2139
2140 # to avoid cyclic rule
2141 if FileType in RuleChain:
2142 break
2143
2144 RuleChain.append(FileType)
2145 SourceList.extend(Target.Outputs)
2146 LastTarget = Target
2147 FileType = TAB_UNKNOWN_FILE
2148
2149 def _GetTargets(self):
2150 if self._BuildTargets == None:
2151 self._IntroBuildTargetList = set()
2152 self._FinalBuildTargetList = set()
2153 self._BuildTargets = {}
2154 self._FileTypes = {}
2155
2156 #TRICK: call _GetSourceFileList to apply build rule for binary files
2157 if self.SourceFileList:
2158 pass
2159
2160 #TRICK: call _GetBinaryFileList to apply build rule for binary files
2161 if self.BinaryFileList:
2162 pass
2163
2164 return self._BuildTargets
2165
2166 def _GetIntroTargetList(self):
2167 self._GetTargets()
2168 return self._IntroBuildTargetList
2169
2170 def _GetFinalTargetList(self):
2171 self._GetTargets()
2172 return self._FinalBuildTargetList
2173
2174 def _GetFileTypes(self):
2175 self._GetTargets()
2176 return self._FileTypes
2177
2178 ## Get the list of package object the module depends on
2179 #
2180 # @retval list The package object list
2181 #
2182 def _GetDependentPackageList(self):
2183 return self.Module.Packages
2184
2185 ## Return the list of auto-generated code file
2186 #
2187 # @retval list The list of auto-generated file
2188 #
2189 def _GetAutoGenFileList(self):
2190 UniStringAutoGenC = True
2191 UniStringBinBuffer = StringIO()
2192 if self.BuildType == 'UEFI_HII':
2193 UniStringAutoGenC = False
2194 if self._AutoGenFileList == None:
2195 self._AutoGenFileList = {}
2196 AutoGenC = TemplateString()
2197 AutoGenH = TemplateString()
2198 StringH = TemplateString()
2199 GenC.CreateCode(self, AutoGenC, AutoGenH, StringH, UniStringAutoGenC, UniStringBinBuffer)
2200 if str(AutoGenC) != "" and TAB_C_CODE_FILE in self.FileTypes:
2201 AutoFile = PathClass(gAutoGenCodeFileName, self.DebugDir)
2202 self._AutoGenFileList[AutoFile] = str(AutoGenC)
2203 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
2204 if str(AutoGenH) != "":
2205 AutoFile = PathClass(gAutoGenHeaderFileName, self.DebugDir)
2206 self._AutoGenFileList[AutoFile] = str(AutoGenH)
2207 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
2208 if str(StringH) != "":
2209 AutoFile = PathClass(gAutoGenStringFileName % {"module_name":self.Name}, self.DebugDir)
2210 self._AutoGenFileList[AutoFile] = str(StringH)
2211 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
2212 if UniStringBinBuffer != None and UniStringBinBuffer.getvalue() != "":
2213 AutoFile = PathClass(gAutoGenStringFormFileName % {"module_name":self.Name}, self.OutputDir)
2214 self._AutoGenFileList[AutoFile] = UniStringBinBuffer.getvalue()
2215 AutoFile.IsBinary = True
2216 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
2217 if UniStringBinBuffer != None:
2218 UniStringBinBuffer.close()
2219 return self._AutoGenFileList
2220
2221 ## Return the list of library modules explicitly or implicityly used by this module
2222 def _GetLibraryList(self):
2223 if self._DependentLibraryList == None:
2224 # only merge library classes and PCD for non-library module
2225 if self.IsLibrary:
2226 self._DependentLibraryList = []
2227 else:
2228 if self.AutoGenVersion < 0x00010005:
2229 self._DependentLibraryList = self.PlatformInfo.ResolveLibraryReference(self.Module)
2230 else:
2231 self._DependentLibraryList = self.PlatformInfo.ApplyLibraryInstance(self.Module)
2232 return self._DependentLibraryList
2233
2234 ## Get the list of PCDs from current module
2235 #
2236 # @retval list The list of PCD
2237 #
2238 def _GetModulePcdList(self):
2239 if self._ModulePcdList == None:
2240 # apply PCD settings from platform
2241 self._ModulePcdList = self.PlatformInfo.ApplyPcdSetting(self.Module, self.Module.Pcds)
2242 return self._ModulePcdList
2243
2244 ## Get the list of PCDs from dependent libraries
2245 #
2246 # @retval list The list of PCD
2247 #
2248 def _GetLibraryPcdList(self):
2249 if self._LibraryPcdList == None:
2250 Pcds = {}
2251 if not self.IsLibrary:
2252 # get PCDs from dependent libraries
2253 for Library in self.DependentLibraryList:
2254 for Key in Library.Pcds:
2255 # skip duplicated PCDs
2256 if Key in self.Module.Pcds or Key in Pcds:
2257 continue
2258 Pcds[Key] = copy.copy(Library.Pcds[Key])
2259 # apply PCD settings from platform
2260 self._LibraryPcdList = self.PlatformInfo.ApplyPcdSetting(self.Module, Pcds)
2261 else:
2262 self._LibraryPcdList = []
2263 return self._LibraryPcdList
2264
2265 ## Get the GUID value mapping
2266 #
2267 # @retval dict The mapping between GUID cname and its value
2268 #
2269 def _GetGuidList(self):
2270 if self._GuidList == None:
2271 self._GuidList = self.Module.Guids
2272 for Library in self.DependentLibraryList:
2273 self._GuidList.update(Library.Guids)
2274 return self._GuidList
2275
2276 ## Get the protocol value mapping
2277 #
2278 # @retval dict The mapping between protocol cname and its value
2279 #
2280 def _GetProtocolList(self):
2281 if self._ProtocolList == None:
2282 self._ProtocolList = self.Module.Protocols
2283 for Library in self.DependentLibraryList:
2284 self._ProtocolList.update(Library.Protocols)
2285 return self._ProtocolList
2286
2287 ## Get the PPI value mapping
2288 #
2289 # @retval dict The mapping between PPI cname and its value
2290 #
2291 def _GetPpiList(self):
2292 if self._PpiList == None:
2293 self._PpiList = self.Module.Ppis
2294 for Library in self.DependentLibraryList:
2295 self._PpiList.update(Library.Ppis)
2296 return self._PpiList
2297
2298 ## Get the list of include search path
2299 #
2300 # @retval list The list path
2301 #
2302 def _GetIncludePathList(self):
2303 if self._IncludePathList == None:
2304 self._IncludePathList = []
2305 if self.AutoGenVersion < 0x00010005:
2306 for Inc in self.Module.Includes:
2307 if Inc not in self._IncludePathList:
2308 self._IncludePathList.append(Inc)
2309 # for r8 modules
2310 Inc = path.join(Inc, self.Arch.capitalize())
2311 if os.path.exists(Inc) and Inc not in self._IncludePathList:
2312 self._IncludePathList.append(Inc)
2313 # r8 module needs to put DEBUG_DIR at the end of search path and not to use SOURCE_DIR all the time
2314 self._IncludePathList.append(self.DebugDir)
2315 else:
2316 self._IncludePathList.append(self.MetaFile.Dir)
2317 self._IncludePathList.append(self.DebugDir)
2318
2319 for Package in self.Module.Packages:
2320 PackageDir = path.join(self.WorkspaceDir, Package.MetaFile.Dir)
2321 if PackageDir not in self._IncludePathList:
2322 self._IncludePathList.append(PackageDir)
2323 for Inc in Package.Includes:
2324 if Inc not in self._IncludePathList:
2325 self._IncludePathList.append(str(Inc))
2326 return self._IncludePathList
2327
2328 ## Create AsBuilt INF file the module
2329 #
2330 def CreateAsBuiltInf(self):
2331 if self.IsAsBuiltInfCreated:
2332 return
2333
2334 # Skip the following code for EDK I inf
2335 if self.AutoGenVersion < 0x00010005:
2336 return
2337
2338 # Skip the following code for libraries
2339 if self.IsLibrary:
2340 return
2341
2342 # Skip the following code for modules with no source files
2343 if self.SourceFileList == None or self.SourceFileList == []:
2344 return
2345
2346 # Skip the following code for modules without any binary files
2347 if self.BinaryFileList <> None and self.BinaryFileList <> []:
2348 return
2349
2350 ### TODO: How to handles mixed source and binary modules
2351
2352 # Find all DynamicEx PCDs used by this module and dependent libraries
2353 # Also find all packages that the DynamicEx PCDs depend on
2354 Pcds = []
2355 Packages = []
2356 for Pcd in self.ModulePcdList + self.LibraryPcdList:
2357 if Pcd.Type in GenC.gDynamicExPcd:
2358 if Pcd not in Pcds:
2359 Pcds += [Pcd]
2360 for Package in self.DerivedPackageList:
2361 if Package not in Packages:
2362 if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, 'DynamicEx') in Package.Pcds:
2363 Packages += [Package]
2364 elif (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, 'Dynamic') in Package.Pcds:
2365 Packages += [Package]
2366
2367 ModuleType = self.ModuleType
2368 if ModuleType == 'UEFI_DRIVER' and self.DepexGenerated:
2369 ModuleType = 'DXE_DRIVER'
2370
2371 AsBuiltInfDict = {
2372 'module_name' : self.Name,
2373 'module_guid' : self.Guid,
2374 'module_module_type' : ModuleType,
2375 'module_version_string' : self.Version,
2376 'module_uefi_specification_version' : [],
2377 'module_pi_specification_version' : [],
2378 'module_arch' : self.Arch,
2379 'package_item' : ['%s' % (Package.MetaFile.File.replace('\\','/')) for Package in Packages],
2380 'binary_item' : [],
2381 'pcd_item' : [],
2382 'flags_item' : []
2383 }
2384
2385 if 'UEFI_SPECIFICATION_VERSION' in self.Specification:
2386 AsBuiltInfDict['module_uefi_specification_version'] += [self.Specification['UEFI_SPECIFICATION_VERSION']]
2387 if 'PI_SPECIFICATION_VERSION' in self.Specification:
2388 AsBuiltInfDict['module_pi_specification_version'] += [self.Specification['PI_SPECIFICATION_VERSION']]
2389
2390 OutputDir = self.OutputDir.replace('\\','/').strip('/')
2391 if self.ModuleType in ['BASE', 'USER_DEFINED']:
2392 for Item in self.CodaTargetList:
2393 File = Item.Target.Path.replace('\\','/').strip('/').replace(OutputDir,'').strip('/')
2394 if Item.Target.Ext.lower() == '.aml':
2395 AsBuiltInfDict['binary_item'] += ['ASL|' + File]
2396 elif Item.Target.Ext.lower() == '.acpi':
2397 AsBuiltInfDict['binary_item'] += ['ACPI|' + File]
2398 else:
2399 AsBuiltInfDict['binary_item'] += ['BIN|' + File]
2400 else:
2401 for Item in self.CodaTargetList:
2402 File = Item.Target.Path.replace('\\','/').strip('/').replace(OutputDir,'').strip('/')
2403 if Item.Target.Ext.lower() == '.efi':
2404 AsBuiltInfDict['binary_item'] += ['PE32|' + self.Name + '.efi']
2405 else:
2406 AsBuiltInfDict['binary_item'] += ['BIN|' + File]
2407 if self.DepexGenerated:
2408 if self.ModuleType in ['PEIM']:
2409 AsBuiltInfDict['binary_item'] += ['PEI_DEPEX|' + self.Name + '.depex']
2410 if self.ModuleType in ['DXE_DRIVER','DXE_RUNTIME_DRIVER','DXE_SAL_DRIVER','UEFI_DRIVER']:
2411 AsBuiltInfDict['binary_item'] += ['DXE_DEPEX|' + self.Name + '.depex']
2412 if self.ModuleType in ['DXE_SMM_DRIVER']:
2413 AsBuiltInfDict['binary_item'] += ['SMM_DEPEX|' + self.Name + '.depex']
2414
2415 for Pcd in Pcds:
2416 AsBuiltInfDict['pcd_item'] += [Pcd.TokenSpaceGuidCName + '.' + Pcd.TokenCName]
2417
2418 for Item in self.BuildOption:
2419 if 'FLAGS' in self.BuildOption[Item]:
2420 AsBuiltInfDict['flags_item'] += ['%s:%s_%s_%s_%s_FLAGS = %s' % (self.ToolChainFamily, self.BuildTarget, self.ToolChain, self.Arch, Item, self.BuildOption[Item]['FLAGS'].strip())]
2421
2422 AsBuiltInf = TemplateString()
2423 AsBuiltInf.Append(gAsBuiltInfHeaderString.Replace(AsBuiltInfDict))
2424
2425 SaveFileOnChange(os.path.join(self.OutputDir, self.Name + '.inf'), str(AsBuiltInf), False)
2426
2427 self.IsAsBuiltInfCreated = True
2428
2429 ## Create makefile for the module and its dependent libraries
2430 #
2431 # @param CreateLibraryMakeFile Flag indicating if or not the makefiles of
2432 # dependent libraries will be created
2433 #
2434 def CreateMakeFile(self, CreateLibraryMakeFile=True):
2435 if self.IsMakeFileCreated:
2436 return
2437
2438 if not self.IsLibrary and CreateLibraryMakeFile:
2439 for LibraryAutoGen in self.LibraryAutoGenList:
2440 LibraryAutoGen.CreateMakeFile()
2441
2442 if len(self.CustomMakefile) == 0:
2443 Makefile = GenMake.ModuleMakefile(self)
2444 else:
2445 Makefile = GenMake.CustomMakefile(self)
2446 if Makefile.Generate():
2447 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated makefile for module %s [%s]" %
2448 (self.Name, self.Arch))
2449 else:
2450 EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of makefile for module %s [%s]" %
2451 (self.Name, self.Arch))
2452
2453 self.IsMakeFileCreated = True
2454
2455 ## Create autogen code for the module and its dependent libraries
2456 #
2457 # @param CreateLibraryCodeFile Flag indicating if or not the code of
2458 # dependent libraries will be created
2459 #
2460 def CreateCodeFile(self, CreateLibraryCodeFile=True):
2461 if self.IsCodeFileCreated:
2462 return
2463
2464 if not self.IsLibrary and CreateLibraryCodeFile:
2465 for LibraryAutoGen in self.LibraryAutoGenList:
2466 LibraryAutoGen.CreateCodeFile()
2467
2468 AutoGenList = []
2469 IgoredAutoGenList = []
2470
2471 for File in self.AutoGenFileList:
2472 if GenC.Generate(File.Path, self.AutoGenFileList[File], File.IsBinary):
2473 #Ignore R8 AutoGen.c
2474 if self.AutoGenVersion < 0x00010005 and File.Name == 'AutoGen.c':
2475 continue
2476
2477 AutoGenList.append(str(File))
2478 else:
2479 IgoredAutoGenList.append(str(File))
2480
2481 # Skip the following code for EDK I inf
2482 if self.AutoGenVersion < 0x00010005:
2483 return
2484
2485 for ModuleType in self.DepexList:
2486 # Ignore empty [depex] section or [depex] section for "USER_DEFINED" module
2487 if len(self.DepexList[ModuleType]) == 0 or ModuleType == "USER_DEFINED":
2488 continue
2489
2490 Dpx = GenDepex.DependencyExpression(self.DepexList[ModuleType], ModuleType, True)
2491 DpxFile = gAutoGenDepexFileName % {"module_name" : self.Name}
2492
2493 if len(Dpx.PostfixNotation) <> 0:
2494 self.DepexGenerated = True
2495
2496 if Dpx.Generate(path.join(self.OutputDir, DpxFile)):
2497 AutoGenList.append(str(DpxFile))
2498 else:
2499 IgoredAutoGenList.append(str(DpxFile))
2500
2501 if IgoredAutoGenList == []:
2502 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated [%s] files for module %s [%s]" %
2503 (" ".join(AutoGenList), self.Name, self.Arch))
2504 elif AutoGenList == []:
2505 EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of [%s] files for module %s [%s]" %
2506 (" ".join(IgoredAutoGenList), self.Name, self.Arch))
2507 else:
2508 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated [%s] (skipped %s) files for module %s [%s]" %
2509 (" ".join(AutoGenList), " ".join(IgoredAutoGenList), self.Name, self.Arch))
2510
2511 self.IsCodeFileCreated = True
2512 return AutoGenList
2513
2514 ## Summarize the ModuleAutoGen objects of all libraries used by this module
2515 def _GetLibraryAutoGenList(self):
2516 if self._LibraryAutoGenList == None:
2517 self._LibraryAutoGenList = []
2518 for Library in self.DependentLibraryList:
2519 La = ModuleAutoGen(
2520 self.Workspace,
2521 Library.MetaFile,
2522 self.BuildTarget,
2523 self.ToolChain,
2524 self.Arch,
2525 self.PlatformInfo.MetaFile
2526 )
2527 if La not in self._LibraryAutoGenList:
2528 self._LibraryAutoGenList.append(La)
2529 for Lib in La.CodaTargetList:
2530 self._ApplyBuildRule(Lib.Target, TAB_UNKNOWN_FILE)
2531 return self._LibraryAutoGenList
2532
2533 Module = property(_GetModule)
2534 Name = property(_GetBaseName)
2535 Guid = property(_GetGuid)
2536 Version = property(_GetVersion)
2537 ModuleType = property(_GetModuleType)
2538 ComponentType = property(_GetComponentType)
2539 BuildType = property(_GetBuildType)
2540 PcdIsDriver = property(_GetPcdIsDriver)
2541 AutoGenVersion = property(_GetAutoGenVersion)
2542 Macros = property(_GetMacros)
2543 Specification = property(_GetSpecification)
2544
2545 IsLibrary = property(_IsLibrary)
2546
2547 BuildDir = property(_GetBuildDir)
2548 OutputDir = property(_GetOutputDir)
2549 DebugDir = property(_GetDebugDir)
2550 MakeFileDir = property(_GetMakeFileDir)
2551 CustomMakefile = property(_GetCustomMakefile)
2552
2553 IncludePathList = property(_GetIncludePathList)
2554 AutoGenFileList = property(_GetAutoGenFileList)
2555 UnicodeFileList = property(_GetUnicodeFileList)
2556 SourceFileList = property(_GetSourceFileList)
2557 BinaryFileList = property(_GetBinaryFiles) # FileType : [File List]
2558 Targets = property(_GetTargets)
2559 IntroTargetList = property(_GetIntroTargetList)
2560 CodaTargetList = property(_GetFinalTargetList)
2561 FileTypes = property(_GetFileTypes)
2562 BuildRules = property(_GetBuildRules)
2563
2564 DependentPackageList = property(_GetDependentPackageList)
2565 DependentLibraryList = property(_GetLibraryList)
2566 LibraryAutoGenList = property(_GetLibraryAutoGenList)
2567 DerivedPackageList = property(_GetDerivedPackageList)
2568
2569 ModulePcdList = property(_GetModulePcdList)
2570 LibraryPcdList = property(_GetLibraryPcdList)
2571 GuidList = property(_GetGuidList)
2572 ProtocolList = property(_GetProtocolList)
2573 PpiList = property(_GetPpiList)
2574 DepexList = property(_GetDepexTokenList)
2575 DepexExpressionList = property(_GetDepexExpressionTokenList)
2576 BuildOption = property(_GetModuleBuildOption)
2577 BuildCommand = property(_GetBuildCommand)
2578
2579 # This acts like the main() function for the script, unless it is 'import'ed into another script.
2580 if __name__ == '__main__':
2581 pass
2582