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