]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/AutoGen/AutoGen.py
This patch is going to:
[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 - 2014, 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 Common.LongFilePathOs as 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.LongFilePathSupport import CopyLongFilePath
30 from Common.BuildToolError import *
31 from Common.DataType import *
32 from Common.Misc import *
33 from Common.String import *
34 import Common.GlobalData as GlobalData
35 from GenFds.FdfParser import *
36 from CommonDataClass.CommonClass import SkuInfoClass
37 from Workspace.BuildClassObject import *
38 from GenPatchPcdTable.GenPatchPcdTable import parsePcdInfoFromMapFile
39 import Common.VpdInfoFile as VpdInfoFile
40 from GenPcdDb import CreatePcdDatabaseCode
41 from Workspace.MetaFileCommentParser import UsageList
42
43 ## Regular expression for splitting Dependency Expression string into tokens
44 gDepexTokenPattern = re.compile("(\(|\)|\w+| \S+\.inf)")
45
46 ## Mapping Makefile type
47 gMakeTypeMap = {"MSFT":"nmake", "GCC":"gmake"}
48
49
50 ## Build rule configuration file
51 gBuildRuleFile = 'Conf/build_rule.txt'
52
53 ## Build rule default version
54 AutoGenReqBuildRuleVerNum = "0.1"
55
56 ## default file name for AutoGen
57 gAutoGenCodeFileName = "AutoGen.c"
58 gAutoGenHeaderFileName = "AutoGen.h"
59 gAutoGenStringFileName = "%(module_name)sStrDefs.h"
60 gAutoGenStringFormFileName = "%(module_name)sStrDefs.hpk"
61 gAutoGenDepexFileName = "%(module_name)s.depex"
62
63 #
64 # Template string to generic AsBuilt INF
65 #
66 gAsBuiltInfHeaderString = TemplateString("""${header_comments}
67
68 [Defines]
69 INF_VERSION = 0x00010016
70 BASE_NAME = ${module_name}
71 FILE_GUID = ${module_guid}
72 MODULE_TYPE = ${module_module_type}
73 VERSION_STRING = ${module_version_string}${BEGIN}
74 PCD_IS_DRIVER = ${pcd_is_driver_string}${END}${BEGIN}
75 UEFI_SPECIFICATION_VERSION = ${module_uefi_specification_version}${END}${BEGIN}
76 PI_SPECIFICATION_VERSION = ${module_pi_specification_version}${END}
77
78 [Packages]${BEGIN}
79 ${package_item}${END}
80
81 [Binaries.${module_arch}]${BEGIN}
82 ${binary_item}${END}
83
84 [PatchPcd.${module_arch}]${BEGIN}
85 ${patchablepcd_item}
86 ${END}
87 [Protocols.${module_arch}]${BEGIN}
88 ${protocol_item}
89 ${END}
90 [Ppis.${module_arch}]${BEGIN}
91 ${ppi_item}
92 ${END}
93 [Guids.${module_arch}]${BEGIN}
94 ${guid_item}
95 ${END}
96 [PcdEx.${module_arch}]${BEGIN}
97 ${pcd_item}
98 ${END}
99
100 ## @AsBuilt${BEGIN}
101 ## ${flags_item}${END}
102 """)
103
104 ## Base class for AutoGen
105 #
106 # This class just implements the cache mechanism of AutoGen objects.
107 #
108 class AutoGen(object):
109 # database to maintain the objects of xxxAutoGen
110 _CACHE_ = {} # (BuildTarget, ToolChain) : {ARCH : {platform file: AutoGen object}}}
111
112 ## Factory method
113 #
114 # @param Class class object of real AutoGen class
115 # (WorkspaceAutoGen, ModuleAutoGen or PlatformAutoGen)
116 # @param Workspace Workspace directory or WorkspaceAutoGen object
117 # @param MetaFile The path of meta file
118 # @param Target Build target
119 # @param Toolchain Tool chain name
120 # @param Arch Target arch
121 # @param *args The specific class related parameters
122 # @param **kwargs The specific class related dict parameters
123 #
124 def __new__(Class, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):
125 # check if the object has been created
126 Key = (Target, Toolchain)
127 if Key not in Class._CACHE_ or Arch not in Class._CACHE_[Key] \
128 or MetaFile not in Class._CACHE_[Key][Arch]:
129 AutoGenObject = super(AutoGen, Class).__new__(Class)
130 # call real constructor
131 if not AutoGenObject._Init(Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):
132 return None
133 if Key not in Class._CACHE_:
134 Class._CACHE_[Key] = {}
135 if Arch not in Class._CACHE_[Key]:
136 Class._CACHE_[Key][Arch] = {}
137 Class._CACHE_[Key][Arch][MetaFile] = AutoGenObject
138 else:
139 AutoGenObject = Class._CACHE_[Key][Arch][MetaFile]
140
141 return AutoGenObject
142
143 ## hash() operator
144 #
145 # The file path of platform file will be used to represent hash value of this object
146 #
147 # @retval int Hash value of the file path of platform file
148 #
149 def __hash__(self):
150 return hash(self.MetaFile)
151
152 ## str() operator
153 #
154 # The file path of platform file will be used to represent this object
155 #
156 # @retval string String of platform file path
157 #
158 def __str__(self):
159 return str(self.MetaFile)
160
161 ## "==" operator
162 def __eq__(self, Other):
163 return Other and self.MetaFile == Other
164
165 ## Workspace AutoGen class
166 #
167 # This class is used mainly to control the whole platform build for different
168 # architecture. This class will generate top level makefile.
169 #
170 class WorkspaceAutoGen(AutoGen):
171 ## Real constructor of WorkspaceAutoGen
172 #
173 # This method behaves the same as __init__ except that it needs explicit invoke
174 # (in super class's __new__ method)
175 #
176 # @param WorkspaceDir Root directory of workspace
177 # @param ActivePlatform Meta-file of active platform
178 # @param Target Build target
179 # @param Toolchain Tool chain name
180 # @param ArchList List of architecture of current build
181 # @param MetaFileDb Database containing meta-files
182 # @param BuildConfig Configuration of build
183 # @param ToolDefinition Tool chain definitions
184 # @param FlashDefinitionFile File of flash definition
185 # @param Fds FD list to be generated
186 # @param Fvs FV list to be generated
187 # @param Caps Capsule list to be generated
188 # @param SkuId SKU id from command line
189 #
190 def _Init(self, WorkspaceDir, ActivePlatform, Target, Toolchain, ArchList, MetaFileDb,
191 BuildConfig, ToolDefinition, FlashDefinitionFile='', Fds=None, Fvs=None, Caps=None, SkuId='', UniFlag=None,
192 Progress=None, BuildModule=None):
193 if Fds is None:
194 Fds = []
195 if Fvs is None:
196 Fvs = []
197 if Caps is None:
198 Caps = []
199 self.BuildDatabase = MetaFileDb
200 self.MetaFile = ActivePlatform
201 self.WorkspaceDir = WorkspaceDir
202 self.Platform = self.BuildDatabase[self.MetaFile, 'COMMON', Target, Toolchain]
203 GlobalData.gActivePlatform = self.Platform
204 self.BuildTarget = Target
205 self.ToolChain = Toolchain
206 self.ArchList = ArchList
207 self.SkuId = SkuId
208 self.UniFlag = UniFlag
209
210 self.TargetTxt = BuildConfig
211 self.ToolDef = ToolDefinition
212 self.FdfFile = FlashDefinitionFile
213 self.FdTargetList = Fds
214 self.FvTargetList = Fvs
215 self.CapTargetList = Caps
216 self.AutoGenObjectList = []
217
218 # there's many relative directory operations, so ...
219 os.chdir(self.WorkspaceDir)
220
221 #
222 # Merge Arch
223 #
224 if not self.ArchList:
225 ArchList = set(self.Platform.SupArchList)
226 else:
227 ArchList = set(self.ArchList) & set(self.Platform.SupArchList)
228 if not ArchList:
229 EdkLogger.error("build", PARAMETER_INVALID,
230 ExtraData = "Invalid ARCH specified. [Valid ARCH: %s]" % (" ".join(self.Platform.SupArchList)))
231 elif self.ArchList and len(ArchList) != len(self.ArchList):
232 SkippedArchList = set(self.ArchList).symmetric_difference(set(self.Platform.SupArchList))
233 EdkLogger.verbose("\nArch [%s] is ignored because the platform supports [%s] only!"
234 % (" ".join(SkippedArchList), " ".join(self.Platform.SupArchList)))
235 self.ArchList = tuple(ArchList)
236
237 # Validate build target
238 if self.BuildTarget not in self.Platform.BuildTargets:
239 EdkLogger.error("build", PARAMETER_INVALID,
240 ExtraData="Build target [%s] is not supported by the platform. [Valid target: %s]"
241 % (self.BuildTarget, " ".join(self.Platform.BuildTargets)))
242
243 # parse FDF file to get PCDs in it, if any
244 if not self.FdfFile:
245 self.FdfFile = self.Platform.FlashDefinition
246
247 EdkLogger.info("")
248 if self.ArchList:
249 EdkLogger.info('%-16s = %s' % ("Architecture(s)", ' '.join(self.ArchList)))
250 EdkLogger.info('%-16s = %s' % ("Build target", self.BuildTarget))
251 EdkLogger.info('%-16s = %s' % ("Toolchain",self.ToolChain))
252
253 EdkLogger.info('\n%-24s = %s' % ("Active Platform", self.Platform))
254 if BuildModule:
255 EdkLogger.info('%-24s = %s' % ("Active Module", BuildModule))
256
257 if self.FdfFile:
258 EdkLogger.info('%-24s = %s' % ("Flash Image Definition", self.FdfFile))
259
260 EdkLogger.verbose("\nFLASH_DEFINITION = %s" % self.FdfFile)
261
262 if Progress:
263 Progress.Start("\nProcessing meta-data")
264
265 if self.FdfFile:
266 #
267 # Mark now build in AutoGen Phase
268 #
269 GlobalData.gAutoGenPhase = True
270 Fdf = FdfParser(self.FdfFile.Path)
271 Fdf.ParseFile()
272 GlobalData.gFdfParser = Fdf
273 GlobalData.gAutoGenPhase = False
274 PcdSet = Fdf.Profile.PcdDict
275 ModuleList = Fdf.Profile.InfList
276 self.FdfProfile = Fdf.Profile
277 for fvname in self.FvTargetList:
278 if fvname.upper() not in self.FdfProfile.FvDict:
279 EdkLogger.error("build", OPTION_VALUE_INVALID,
280 "No such an FV in FDF file: %s" % fvname)
281 else:
282 PcdSet = {}
283 ModuleList = []
284 self.FdfProfile = None
285 if self.FdTargetList:
286 EdkLogger.info("No flash definition file found. FD [%s] will be ignored." % " ".join(self.FdTargetList))
287 self.FdTargetList = []
288 if self.FvTargetList:
289 EdkLogger.info("No flash definition file found. FV [%s] will be ignored." % " ".join(self.FvTargetList))
290 self.FvTargetList = []
291 if self.CapTargetList:
292 EdkLogger.info("No flash definition file found. Capsule [%s] will be ignored." % " ".join(self.CapTargetList))
293 self.CapTargetList = []
294
295 # apply SKU and inject PCDs from Flash Definition file
296 for Arch in self.ArchList:
297 Platform = self.BuildDatabase[self.MetaFile, Arch, Target, Toolchain]
298
299 DecPcds = {}
300 DecPcdsKey = set()
301 PGen = PlatformAutoGen(self, self.MetaFile, Target, Toolchain, Arch)
302 PkgSet = set()
303 for Inf in ModuleList:
304 ModuleFile = PathClass(NormPath(Inf), GlobalData.gWorkspace, Arch)
305 if ModuleFile in Platform.Modules:
306 continue
307 ModuleData = self.BuildDatabase[ModuleFile, Arch, Target, Toolchain]
308 PkgSet.update(ModuleData.Packages)
309 Pkgs = list(PkgSet) + list(PGen.PackageList)
310 for Pkg in Pkgs:
311 for Pcd in Pkg.Pcds:
312 DecPcds[Pcd[0], Pcd[1]] = Pkg.Pcds[Pcd]
313 DecPcdsKey.add((Pcd[0], Pcd[1], Pcd[2]))
314
315 Platform.SkuName = self.SkuId
316 for Name, Guid in PcdSet:
317 if (Name, Guid) not in DecPcds:
318 EdkLogger.error(
319 'build',
320 PARSER_ERROR,
321 "PCD (%s.%s) used in FDF is not declared in DEC files." % (Guid, Name),
322 File = self.FdfProfile.PcdFileLineDict[Name, Guid][0],
323 Line = self.FdfProfile.PcdFileLineDict[Name, Guid][1]
324 )
325 else:
326 # Check whether Dynamic or DynamicEx PCD used in FDF file. If used, build break and give a error message.
327 if (Name, Guid, TAB_PCDS_FIXED_AT_BUILD) in DecPcdsKey \
328 or (Name, Guid, TAB_PCDS_PATCHABLE_IN_MODULE) in DecPcdsKey \
329 or (Name, Guid, TAB_PCDS_FEATURE_FLAG) in DecPcdsKey:
330 Platform.AddPcd(Name, Guid, PcdSet[Name, Guid])
331 continue
332 elif (Name, Guid, TAB_PCDS_DYNAMIC) in DecPcdsKey or (Name, Guid, TAB_PCDS_DYNAMIC_EX) in DecPcdsKey:
333 EdkLogger.error(
334 'build',
335 PARSER_ERROR,
336 "Using Dynamic or DynamicEx type of PCD [%s.%s] in FDF file is not allowed." % (Guid, Name),
337 File = self.FdfProfile.PcdFileLineDict[Name, Guid][0],
338 Line = self.FdfProfile.PcdFileLineDict[Name, Guid][1]
339 )
340
341 Pa = PlatformAutoGen(self, self.MetaFile, Target, Toolchain, Arch)
342 #
343 # Explicitly collect platform's dynamic PCDs
344 #
345 Pa.CollectPlatformDynamicPcds()
346 Pa.CollectFixedAtBuildPcds()
347 self.AutoGenObjectList.append(Pa)
348
349 #
350 # Check PCDs token value conflict in each DEC file.
351 #
352 self._CheckAllPcdsTokenValueConflict()
353
354 #
355 # Check PCD type and definition between DSC and DEC
356 #
357 self._CheckPcdDefineAndType()
358
359 if self.FdfFile:
360 self._CheckDuplicateInFV(Fdf)
361
362 self._BuildDir = None
363 self._FvDir = None
364 self._MakeFileDir = None
365 self._BuildCommand = None
366
367 return True
368
369 ## _CheckDuplicateInFV() method
370 #
371 # Check whether there is duplicate modules/files exist in FV section.
372 # The check base on the file GUID;
373 #
374 def _CheckDuplicateInFV(self, Fdf):
375 for Fv in Fdf.Profile.FvDict:
376 _GuidDict = {}
377 for FfsFile in Fdf.Profile.FvDict[Fv].FfsList:
378 if FfsFile.InfFileName and FfsFile.NameGuid == None:
379 #
380 # Get INF file GUID
381 #
382 InfFoundFlag = False
383 for Pa in self.AutoGenObjectList:
384 if InfFoundFlag:
385 break
386 for Module in Pa.ModuleAutoGenList:
387 if path.normpath(Module.MetaFile.File) == path.normpath(FfsFile.InfFileName):
388 InfFoundFlag = True
389 if not Module.Guid.upper() in _GuidDict.keys():
390 _GuidDict[Module.Guid.upper()] = FfsFile
391 break
392 else:
393 EdkLogger.error("build",
394 FORMAT_INVALID,
395 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s"%(FfsFile.CurrentLineNum,
396 FfsFile.CurrentLineContent,
397 _GuidDict[Module.Guid.upper()].CurrentLineNum,
398 _GuidDict[Module.Guid.upper()].CurrentLineContent,
399 Module.Guid.upper()),
400 ExtraData=self.FdfFile)
401 #
402 # Some INF files not have entity in DSC file.
403 #
404 if not InfFoundFlag:
405 if FfsFile.InfFileName.find('$') == -1:
406 InfPath = NormPath(FfsFile.InfFileName)
407 if not os.path.exists(InfPath):
408 EdkLogger.error('build', GENFDS_ERROR, "Non-existant Module %s !" % (FfsFile.InfFileName))
409
410 PathClassObj = PathClass(FfsFile.InfFileName, self.WorkspaceDir)
411 #
412 # Here we just need to get FILE_GUID from INF file, use 'COMMON' as ARCH attribute. and use
413 # BuildObject from one of AutoGenObjectList is enough.
414 #
415 InfObj = self.AutoGenObjectList[0].BuildDatabase.WorkspaceDb.BuildObject[PathClassObj, 'COMMON', self.BuildTarget, self.ToolChain]
416 if not InfObj.Guid.upper() in _GuidDict.keys():
417 _GuidDict[InfObj.Guid.upper()] = FfsFile
418 else:
419 EdkLogger.error("build",
420 FORMAT_INVALID,
421 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s"%(FfsFile.CurrentLineNum,
422 FfsFile.CurrentLineContent,
423 _GuidDict[InfObj.Guid.upper()].CurrentLineNum,
424 _GuidDict[InfObj.Guid.upper()].CurrentLineContent,
425 InfObj.Guid.upper()),
426 ExtraData=self.FdfFile)
427 InfFoundFlag = False
428
429 if FfsFile.NameGuid != None:
430 _CheckPCDAsGuidPattern = re.compile("^PCD\(.+\..+\)$")
431
432 #
433 # If the NameGuid reference a PCD name.
434 # The style must match: PCD(xxxx.yyy)
435 #
436 if _CheckPCDAsGuidPattern.match(FfsFile.NameGuid):
437 #
438 # Replace the PCD value.
439 #
440 _PcdName = FfsFile.NameGuid.lstrip("PCD(").rstrip(")")
441 PcdFoundFlag = False
442 for Pa in self.AutoGenObjectList:
443 if not PcdFoundFlag:
444 for PcdItem in Pa.AllPcdList:
445 if (PcdItem.TokenSpaceGuidCName + "." + PcdItem.TokenCName) == _PcdName:
446 #
447 # First convert from CFormatGuid to GUID string
448 #
449 _PcdGuidString = GuidStructureStringToGuidString(PcdItem.DefaultValue)
450
451 if not _PcdGuidString:
452 #
453 # Then try Byte array.
454 #
455 _PcdGuidString = GuidStructureByteArrayToGuidString(PcdItem.DefaultValue)
456
457 if not _PcdGuidString:
458 #
459 # Not Byte array or CFormat GUID, raise error.
460 #
461 EdkLogger.error("build",
462 FORMAT_INVALID,
463 "The format of PCD value is incorrect. PCD: %s , Value: %s\n"%(_PcdName, PcdItem.DefaultValue),
464 ExtraData=self.FdfFile)
465
466 if not _PcdGuidString.upper() in _GuidDict.keys():
467 _GuidDict[_PcdGuidString.upper()] = FfsFile
468 PcdFoundFlag = True
469 break
470 else:
471 EdkLogger.error("build",
472 FORMAT_INVALID,
473 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s"%(FfsFile.CurrentLineNum,
474 FfsFile.CurrentLineContent,
475 _GuidDict[_PcdGuidString.upper()].CurrentLineNum,
476 _GuidDict[_PcdGuidString.upper()].CurrentLineContent,
477 FfsFile.NameGuid.upper()),
478 ExtraData=self.FdfFile)
479
480 if not FfsFile.NameGuid.upper() in _GuidDict.keys():
481 _GuidDict[FfsFile.NameGuid.upper()] = FfsFile
482 else:
483 #
484 # Two raw file GUID conflict.
485 #
486 EdkLogger.error("build",
487 FORMAT_INVALID,
488 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s"%(FfsFile.CurrentLineNum,
489 FfsFile.CurrentLineContent,
490 _GuidDict[FfsFile.NameGuid.upper()].CurrentLineNum,
491 _GuidDict[FfsFile.NameGuid.upper()].CurrentLineContent,
492 FfsFile.NameGuid.upper()),
493 ExtraData=self.FdfFile)
494
495
496 def _CheckPcdDefineAndType(self):
497 PcdTypeList = [
498 "FixedAtBuild", "PatchableInModule", "FeatureFlag",
499 "Dynamic", #"DynamicHii", "DynamicVpd",
500 "DynamicEx", # "DynamicExHii", "DynamicExVpd"
501 ]
502
503 # This dict store PCDs which are not used by any modules with specified arches
504 UnusedPcd = sdict()
505 for Pa in self.AutoGenObjectList:
506 # Key of DSC's Pcds dictionary is PcdCName, TokenSpaceGuid
507 for Pcd in Pa.Platform.Pcds:
508 PcdType = Pa.Platform.Pcds[Pcd].Type
509
510 # If no PCD type, this PCD comes from FDF
511 if not PcdType:
512 continue
513
514 # Try to remove Hii and Vpd suffix
515 if PcdType.startswith("DynamicEx"):
516 PcdType = "DynamicEx"
517 elif PcdType.startswith("Dynamic"):
518 PcdType = "Dynamic"
519
520 for Package in Pa.PackageList:
521 # Key of DEC's Pcds dictionary is PcdCName, TokenSpaceGuid, PcdType
522 if (Pcd[0], Pcd[1], PcdType) in Package.Pcds:
523 break
524 for Type in PcdTypeList:
525 if (Pcd[0], Pcd[1], Type) in Package.Pcds:
526 EdkLogger.error(
527 'build',
528 FORMAT_INVALID,
529 "Type [%s] of PCD [%s.%s] in DSC file doesn't match the type [%s] defined in DEC file." \
530 % (Pa.Platform.Pcds[Pcd].Type, Pcd[1], Pcd[0], Type),
531 ExtraData=None
532 )
533 return
534 else:
535 UnusedPcd.setdefault(Pcd, []).append(Pa.Arch)
536
537 for Pcd in UnusedPcd:
538 EdkLogger.warn(
539 'build',
540 "The PCD was not specified by any INF module in the platform for the given architecture.\n"
541 "\tPCD: [%s.%s]\n\tPlatform: [%s]\n\tArch: %s"
542 % (Pcd[1], Pcd[0], os.path.basename(str(self.MetaFile)), str(UnusedPcd[Pcd])),
543 ExtraData=None
544 )
545
546 def __repr__(self):
547 return "%s [%s]" % (self.MetaFile, ", ".join(self.ArchList))
548
549 ## Return the directory to store FV files
550 def _GetFvDir(self):
551 if self._FvDir == None:
552 self._FvDir = path.join(self.BuildDir, 'FV')
553 return self._FvDir
554
555 ## Return the directory to store all intermediate and final files built
556 def _GetBuildDir(self):
557 return self.AutoGenObjectList[0].BuildDir
558
559 ## Return the build output directory platform specifies
560 def _GetOutputDir(self):
561 return self.Platform.OutputDirectory
562
563 ## Return platform name
564 def _GetName(self):
565 return self.Platform.PlatformName
566
567 ## Return meta-file GUID
568 def _GetGuid(self):
569 return self.Platform.Guid
570
571 ## Return platform version
572 def _GetVersion(self):
573 return self.Platform.Version
574
575 ## Return paths of tools
576 def _GetToolDefinition(self):
577 return self.AutoGenObjectList[0].ToolDefinition
578
579 ## Return directory of platform makefile
580 #
581 # @retval string Makefile directory
582 #
583 def _GetMakeFileDir(self):
584 if self._MakeFileDir == None:
585 self._MakeFileDir = self.BuildDir
586 return self._MakeFileDir
587
588 ## Return build command string
589 #
590 # @retval string Build command string
591 #
592 def _GetBuildCommand(self):
593 if self._BuildCommand == None:
594 # BuildCommand should be all the same. So just get one from platform AutoGen
595 self._BuildCommand = self.AutoGenObjectList[0].BuildCommand
596 return self._BuildCommand
597
598 ## Check the PCDs token value conflict in each DEC file.
599 #
600 # Will cause build break and raise error message while two PCDs conflict.
601 #
602 # @return None
603 #
604 def _CheckAllPcdsTokenValueConflict(self):
605 for Pa in self.AutoGenObjectList:
606 for Package in Pa.PackageList:
607 PcdList = Package.Pcds.values()
608 PcdList.sort(lambda x, y: cmp(x.TokenValue, y.TokenValue))
609 Count = 0
610 while (Count < len(PcdList) - 1) :
611 Item = PcdList[Count]
612 ItemNext = PcdList[Count + 1]
613 #
614 # Make sure in the same token space the TokenValue should be unique
615 #
616 if (Item.TokenValue == ItemNext.TokenValue):
617 SameTokenValuePcdList = []
618 SameTokenValuePcdList.append(Item)
619 SameTokenValuePcdList.append(ItemNext)
620 RemainPcdListLength = len(PcdList) - Count - 2
621 for ValueSameCount in range(RemainPcdListLength):
622 if PcdList[len(PcdList) - RemainPcdListLength + ValueSameCount].TokenValue == Item.TokenValue:
623 SameTokenValuePcdList.append(PcdList[len(PcdList) - RemainPcdListLength + ValueSameCount])
624 else:
625 break;
626 #
627 # Sort same token value PCD list with TokenGuid and TokenCName
628 #
629 SameTokenValuePcdList.sort(lambda x, y: cmp("%s.%s"%(x.TokenSpaceGuidCName, x.TokenCName), "%s.%s"%(y.TokenSpaceGuidCName, y.TokenCName)))
630 SameTokenValuePcdListCount = 0
631 while (SameTokenValuePcdListCount < len(SameTokenValuePcdList) - 1):
632 TemListItem = SameTokenValuePcdList[SameTokenValuePcdListCount]
633 TemListItemNext = SameTokenValuePcdList[SameTokenValuePcdListCount + 1]
634
635 if (TemListItem.TokenSpaceGuidCName == TemListItemNext.TokenSpaceGuidCName) and (TemListItem.TokenCName != TemListItemNext.TokenCName):
636 EdkLogger.error(
637 'build',
638 FORMAT_INVALID,
639 "The TokenValue [%s] of PCD [%s.%s] is conflict with: [%s.%s] in %s"\
640 % (TemListItem.TokenValue, TemListItem.TokenSpaceGuidCName, TemListItem.TokenCName, TemListItemNext.TokenSpaceGuidCName, TemListItemNext.TokenCName, Package),
641 ExtraData=None
642 )
643 SameTokenValuePcdListCount += 1
644 Count += SameTokenValuePcdListCount
645 Count += 1
646
647 PcdList = Package.Pcds.values()
648 PcdList.sort(lambda x, y: cmp("%s.%s"%(x.TokenSpaceGuidCName, x.TokenCName), "%s.%s"%(y.TokenSpaceGuidCName, y.TokenCName)))
649 Count = 0
650 while (Count < len(PcdList) - 1) :
651 Item = PcdList[Count]
652 ItemNext = PcdList[Count + 1]
653 #
654 # Check PCDs with same TokenSpaceGuidCName.TokenCName have same token value as well.
655 #
656 if (Item.TokenSpaceGuidCName == ItemNext.TokenSpaceGuidCName) and (Item.TokenCName == ItemNext.TokenCName) and (Item.TokenValue != ItemNext.TokenValue):
657 EdkLogger.error(
658 'build',
659 FORMAT_INVALID,
660 "The TokenValue [%s] of PCD [%s.%s] in %s defined in two places should be same as well."\
661 % (Item.TokenValue, Item.TokenSpaceGuidCName, Item.TokenCName, Package),
662 ExtraData=None
663 )
664 Count += 1
665
666 def _GenFdsCommand(self):
667 return (GenMake.TopLevelMakefile(self)._TEMPLATE_.Replace(GenMake.TopLevelMakefile(self)._TemplateDict)).strip()
668
669 ## Create makefile for the platform and modules in it
670 #
671 # @param CreateDepsMakeFile Flag indicating if the makefile for
672 # modules will be created as well
673 #
674 def CreateMakeFile(self, CreateDepsMakeFile=False):
675 if CreateDepsMakeFile:
676 for Pa in self.AutoGenObjectList:
677 Pa.CreateMakeFile(CreateDepsMakeFile)
678
679 ## Create autogen code for platform and modules
680 #
681 # Since there's no autogen code for platform, this method will do nothing
682 # if CreateModuleCodeFile is set to False.
683 #
684 # @param CreateDepsCodeFile Flag indicating if creating module's
685 # autogen code file or not
686 #
687 def CreateCodeFile(self, CreateDepsCodeFile=False):
688 if not CreateDepsCodeFile:
689 return
690 for Pa in self.AutoGenObjectList:
691 Pa.CreateCodeFile(CreateDepsCodeFile)
692
693 ## Create AsBuilt INF file the platform
694 #
695 def CreateAsBuiltInf(self):
696 return
697
698 Name = property(_GetName)
699 Guid = property(_GetGuid)
700 Version = property(_GetVersion)
701 OutputDir = property(_GetOutputDir)
702
703 ToolDefinition = property(_GetToolDefinition) # toolcode : tool path
704
705 BuildDir = property(_GetBuildDir)
706 FvDir = property(_GetFvDir)
707 MakeFileDir = property(_GetMakeFileDir)
708 BuildCommand = property(_GetBuildCommand)
709 GenFdsCommand = property(_GenFdsCommand)
710
711 ## AutoGen class for platform
712 #
713 # PlatformAutoGen class will process the original information in platform
714 # file in order to generate makefile for platform.
715 #
716 class PlatformAutoGen(AutoGen):
717 #
718 # Used to store all PCDs for both PEI and DXE phase, in order to generate
719 # correct PCD database
720 #
721 _DynaPcdList_ = []
722 _NonDynaPcdList_ = []
723
724 #
725 # The priority list while override build option
726 #
727 PrioList = {"0x11111" : 16, # TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE (Highest)
728 "0x01111" : 15, # ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
729 "0x10111" : 14, # TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE
730 "0x00111" : 13, # ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE
731 "0x11011" : 12, # TARGET_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
732 "0x01011" : 11, # ******_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
733 "0x10011" : 10, # TARGET_*********_****_COMMANDTYPE_ATTRIBUTE
734 "0x00011" : 9, # ******_*********_****_COMMANDTYPE_ATTRIBUTE
735 "0x11101" : 8, # TARGET_TOOLCHAIN_ARCH_***********_ATTRIBUTE
736 "0x01101" : 7, # ******_TOOLCHAIN_ARCH_***********_ATTRIBUTE
737 "0x10101" : 6, # TARGET_*********_ARCH_***********_ATTRIBUTE
738 "0x00101" : 5, # ******_*********_ARCH_***********_ATTRIBUTE
739 "0x11001" : 4, # TARGET_TOOLCHAIN_****_***********_ATTRIBUTE
740 "0x01001" : 3, # ******_TOOLCHAIN_****_***********_ATTRIBUTE
741 "0x10001" : 2, # TARGET_*********_****_***********_ATTRIBUTE
742 "0x00001" : 1} # ******_*********_****_***********_ATTRIBUTE (Lowest)
743
744 ## The real constructor of PlatformAutoGen
745 #
746 # This method is not supposed to be called by users of PlatformAutoGen. It's
747 # only used by factory method __new__() to do real initialization work for an
748 # object of PlatformAutoGen
749 #
750 # @param Workspace WorkspaceAutoGen object
751 # @param PlatformFile Platform file (DSC file)
752 # @param Target Build target (DEBUG, RELEASE)
753 # @param Toolchain Name of tool chain
754 # @param Arch arch of the platform supports
755 #
756 def _Init(self, Workspace, PlatformFile, Target, Toolchain, Arch):
757 EdkLogger.debug(EdkLogger.DEBUG_9, "AutoGen platform [%s] [%s]" % (PlatformFile, Arch))
758 GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (PlatformFile, Arch, Toolchain, Target)
759
760 self.MetaFile = PlatformFile
761 self.Workspace = Workspace
762 self.WorkspaceDir = Workspace.WorkspaceDir
763 self.ToolChain = Toolchain
764 self.BuildTarget = Target
765 self.Arch = Arch
766 self.SourceDir = PlatformFile.SubDir
767 self.SourceOverrideDir = None
768 self.FdTargetList = self.Workspace.FdTargetList
769 self.FvTargetList = self.Workspace.FvTargetList
770 self.AllPcdList = []
771 # get the original module/package/platform objects
772 self.BuildDatabase = Workspace.BuildDatabase
773
774 # flag indicating if the makefile/C-code file has been created or not
775 self.IsMakeFileCreated = False
776 self.IsCodeFileCreated = False
777
778 self._Platform = None
779 self._Name = None
780 self._Guid = None
781 self._Version = None
782
783 self._BuildRule = None
784 self._SourceDir = None
785 self._BuildDir = None
786 self._OutputDir = None
787 self._FvDir = None
788 self._MakeFileDir = None
789 self._FdfFile = None
790
791 self._PcdTokenNumber = None # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
792 self._DynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
793 self._NonDynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
794 self._NonDynamicPcdDict = {}
795
796 self._ToolDefinitions = None
797 self._ToolDefFile = None # toolcode : tool path
798 self._ToolChainFamily = None
799 self._BuildRuleFamily = None
800 self._BuildOption = None # toolcode : option
801 self._EdkBuildOption = None # edktoolcode : option
802 self._EdkIIBuildOption = None # edkiitoolcode : option
803 self._PackageList = None
804 self._ModuleAutoGenList = None
805 self._LibraryAutoGenList = None
806 self._BuildCommand = None
807 self._AsBuildInfList = []
808 self._AsBuildModuleList = []
809 if GlobalData.gFdfParser != None:
810 self._AsBuildInfList = GlobalData.gFdfParser.Profile.InfList
811 for Inf in self._AsBuildInfList:
812 InfClass = PathClass(NormPath(Inf), GlobalData.gWorkspace, self.Arch)
813 M = self.BuildDatabase[InfClass, self.Arch, self.BuildTarget, self.ToolChain]
814 if not M.IsSupportedArch:
815 continue
816 self._AsBuildModuleList.append(InfClass)
817 # get library/modules for build
818 self.LibraryBuildDirectoryList = []
819 self.ModuleBuildDirectoryList = []
820 # get the original module/package/platform objects
821 self.LibraryBuildDirectoryList = []
822 self.ModuleBuildDirectoryList = []
823 return True
824
825 def __repr__(self):
826 return "%s [%s]" % (self.MetaFile, self.Arch)
827
828 ## Create autogen code for platform and modules
829 #
830 # Since there's no autogen code for platform, this method will do nothing
831 # if CreateModuleCodeFile is set to False.
832 #
833 # @param CreateModuleCodeFile Flag indicating if creating module's
834 # autogen code file or not
835 #
836 def CreateCodeFile(self, CreateModuleCodeFile=False):
837 # only module has code to be greated, so do nothing if CreateModuleCodeFile is False
838 if self.IsCodeFileCreated or not CreateModuleCodeFile:
839 return
840
841 for Ma in self.ModuleAutoGenList:
842 Ma.CreateCodeFile(True)
843
844 # don't do this twice
845 self.IsCodeFileCreated = True
846
847 ## Generate Fds Command
848 def _GenFdsCommand(self):
849 return self.Workspace.GenFdsCommand
850
851 ## Create makefile for the platform and mdoules in it
852 #
853 # @param CreateModuleMakeFile Flag indicating if the makefile for
854 # modules will be created as well
855 #
856 def CreateMakeFile(self, CreateModuleMakeFile=False):
857 if CreateModuleMakeFile:
858 for ModuleFile in self.Platform.Modules:
859 Ma = ModuleAutoGen(self.Workspace, ModuleFile, self.BuildTarget,
860 self.ToolChain, self.Arch, self.MetaFile)
861 Ma.CreateMakeFile(True)
862 Ma.CreateAsBuiltInf()
863
864 # no need to create makefile for the platform more than once
865 if self.IsMakeFileCreated:
866 return
867
868 # create library/module build dirs for platform
869 Makefile = GenMake.PlatformMakefile(self)
870 self.LibraryBuildDirectoryList = Makefile.GetLibraryBuildDirectoryList()
871 self.ModuleBuildDirectoryList = Makefile.GetModuleBuildDirectoryList()
872
873 self.IsMakeFileCreated = True
874
875 ## Deal with Shared FixedAtBuild Pcds
876 #
877 def CollectFixedAtBuildPcds(self):
878 for LibAuto in self.LibraryAutoGenList:
879 FixedAtBuildPcds = {}
880 ShareFixedAtBuildPcdsSameValue = {}
881 for Module in LibAuto._ReferenceModules:
882 for Pcd in Module.FixedAtBuildPcds + LibAuto.FixedAtBuildPcds:
883 key = ".".join((Pcd.TokenSpaceGuidCName,Pcd.TokenCName))
884 if key not in FixedAtBuildPcds:
885 ShareFixedAtBuildPcdsSameValue[key] = True
886 FixedAtBuildPcds[key] = Pcd.DefaultValue
887 else:
888 if FixedAtBuildPcds[key] != Pcd.DefaultValue:
889 ShareFixedAtBuildPcdsSameValue[key] = False
890 for Pcd in LibAuto.FixedAtBuildPcds:
891 key = ".".join((Pcd.TokenSpaceGuidCName,Pcd.TokenCName))
892 if (Pcd.TokenCName,Pcd.TokenSpaceGuidCName) not in self.NonDynamicPcdDict:
893 continue
894 else:
895 DscPcd = self.NonDynamicPcdDict[(Pcd.TokenCName,Pcd.TokenSpaceGuidCName)]
896 if DscPcd.Type != "FixedAtBuild":
897 continue
898 if key in ShareFixedAtBuildPcdsSameValue and ShareFixedAtBuildPcdsSameValue[key]:
899 LibAuto.ConstPcd[key] = Pcd.DefaultValue
900
901 ## Collect dynamic PCDs
902 #
903 # Gather dynamic PCDs list from each module and their settings from platform
904 # This interface should be invoked explicitly when platform action is created.
905 #
906 def CollectPlatformDynamicPcds(self):
907 # for gathering error information
908 NoDatumTypePcdList = set()
909 PcdNotInDb = []
910 self._GuidValue = {}
911 FdfModuleList = []
912 for InfName in self._AsBuildInfList:
913 InfName = os.path.join(self.WorkspaceDir, InfName)
914 FdfModuleList.append(os.path.normpath(InfName))
915 for F in self.Platform.Modules.keys():
916 M = ModuleAutoGen(self.Workspace, F, self.BuildTarget, self.ToolChain, self.Arch, self.MetaFile)
917 #GuidValue.update(M.Guids)
918
919 self.Platform.Modules[F].M = M
920
921 for PcdFromModule in M.ModulePcdList+M.LibraryPcdList:
922 # make sure that the "VOID*" kind of datum has MaxDatumSize set
923 if PcdFromModule.DatumType == "VOID*" and PcdFromModule.MaxDatumSize in [None, '']:
924 NoDatumTypePcdList.add("%s.%s [%s]" % (PcdFromModule.TokenSpaceGuidCName, PcdFromModule.TokenCName, F))
925
926 if M.IsBinaryModule == True:
927 PcdFromModule.IsFromBinaryInf = True
928 if (PcdFromModule.TokenCName, PcdFromModule.TokenSpaceGuidCName) in self.Platform.Pcds.keys():
929 PcdFromModule.IsFromDsc = True
930 else:
931 PcdFromModule.IsFromDsc = False
932 if PcdFromModule.Type in GenC.gDynamicPcd or PcdFromModule.Type in GenC.gDynamicExPcd:
933 if F.Path not in FdfModuleList:
934 # If one of the Source built modules listed in the DSC is not listed
935 # in FDF modules, and the INF lists a PCD can only use the PcdsDynamic
936 # access method (it is only listed in the DEC file that declares the
937 # PCD as PcdsDynamic), then build tool will report warning message
938 # notify the PI that they are attempting to build a module that must
939 # be included in a flash image in order to be functional. These Dynamic
940 # PCD will not be added into the Database unless it is used by other
941 # modules that are included in the FDF file.
942 if PcdFromModule.Type in GenC.gDynamicPcd and \
943 PcdFromModule.IsFromBinaryInf == False:
944 # Print warning message to let the developer make a determine.
945 if PcdFromModule not in PcdNotInDb:
946 EdkLogger.warn("build",
947 "A PCD listed in the DSC (%s.%s, %s) is used by a module not in the FDF. If the PCD is not used by any module listed in the FDF this PCD will be ignored. " \
948 % (PcdFromModule.TokenSpaceGuidCName, PcdFromModule.TokenCName, self.Platform.MetaFile.Path),
949 File=self.MetaFile, \
950 ExtraData=None)
951 PcdNotInDb.append(PcdFromModule)
952 continue
953 # If one of the Source built modules listed in the DSC is not listed in
954 # FDF modules, and the INF lists a PCD can only use the PcdsDynamicEx
955 # access method (it is only listed in the DEC file that declares the
956 # PCD as PcdsDynamicEx), then DO NOT break the build; DO NOT add the
957 # PCD to the Platform's PCD Database.
958 if PcdFromModule.Type in GenC.gDynamicExPcd:
959 if PcdFromModule not in PcdNotInDb:
960 PcdNotInDb.append(PcdFromModule)
961 continue
962 #
963 # If a dynamic PCD used by a PEM module/PEI module & DXE module,
964 # it should be stored in Pcd PEI database, If a dynamic only
965 # used by DXE module, it should be stored in DXE PCD database.
966 # The default Phase is DXE
967 #
968 if M.ModuleType in ["PEIM", "PEI_CORE"]:
969 PcdFromModule.Phase = "PEI"
970 if PcdFromModule not in self._DynaPcdList_:
971 self._DynaPcdList_.append(PcdFromModule)
972 elif PcdFromModule.Phase == 'PEI':
973 # overwrite any the same PCD existing, if Phase is PEI
974 Index = self._DynaPcdList_.index(PcdFromModule)
975 self._DynaPcdList_[Index] = PcdFromModule
976 elif PcdFromModule not in self._NonDynaPcdList_:
977 self._NonDynaPcdList_.append(PcdFromModule)
978 elif PcdFromModule in self._NonDynaPcdList_ and PcdFromModule.IsFromBinaryInf == True:
979 Index = self._NonDynaPcdList_.index(PcdFromModule)
980 if self._NonDynaPcdList_[Index].IsFromBinaryInf == False:
981 #The PCD from Binary INF will override the same one from source INF
982 self._NonDynaPcdList_.remove (self._NonDynaPcdList_[Index])
983 PcdFromModule.Pending = False
984 self._NonDynaPcdList_.append (PcdFromModule)
985 # Parse the DynamicEx PCD from the AsBuild INF module list of FDF.
986 DscModuleList = []
987 for ModuleInf in self.Platform.Modules.keys():
988 DscModuleList.append (os.path.normpath(ModuleInf.Path))
989 # add the PCD from modules that listed in FDF but not in DSC to Database
990 for InfName in FdfModuleList:
991 if InfName not in DscModuleList:
992 InfClass = PathClass(InfName)
993 M = self.BuildDatabase[InfClass, self.Arch, self.BuildTarget, self.ToolChain]
994 # If a module INF in FDF but not in current arch's DSC module list, it must be module (either binary or source)
995 # for different Arch. PCDs in source module for different Arch is already added before, so skip the source module here.
996 # For binary module, if in current arch, we need to list the PCDs into database.
997 if not M.IsSupportedArch:
998 continue
999 # Override the module PCD setting by platform setting
1000 ModulePcdList = self.ApplyPcdSetting(M, M.Pcds)
1001 for PcdFromModule in ModulePcdList:
1002 PcdFromModule.IsFromBinaryInf = True
1003 PcdFromModule.IsFromDsc = False
1004 # Only allow the DynamicEx and Patchable PCD in AsBuild INF
1005 if PcdFromModule.Type not in GenC.gDynamicExPcd and PcdFromModule.Type not in TAB_PCDS_PATCHABLE_IN_MODULE:
1006 EdkLogger.error("build", AUTOGEN_ERROR, "PCD setting error",
1007 File=self.MetaFile,
1008 ExtraData="\n\tExisted %s PCD %s in:\n\t\t%s\n"
1009 % (PcdFromModule.Type, PcdFromModule.TokenCName, InfName))
1010 # make sure that the "VOID*" kind of datum has MaxDatumSize set
1011 if PcdFromModule.DatumType == "VOID*" and PcdFromModule.MaxDatumSize in [None, '']:
1012 NoDatumTypePcdList.add("%s.%s [%s]" % (PcdFromModule.TokenSpaceGuidCName, PcdFromModule.TokenCName, InfName))
1013 if M.ModuleType in ["PEIM", "PEI_CORE"]:
1014 PcdFromModule.Phase = "PEI"
1015 if PcdFromModule not in self._DynaPcdList_ and PcdFromModule.Type in GenC.gDynamicExPcd:
1016 self._DynaPcdList_.append(PcdFromModule)
1017 elif PcdFromModule not in self._NonDynaPcdList_ and PcdFromModule.Type in TAB_PCDS_PATCHABLE_IN_MODULE:
1018 self._NonDynaPcdList_.append(PcdFromModule)
1019 if PcdFromModule in self._DynaPcdList_ and PcdFromModule.Phase == 'PEI' and PcdFromModule.Type in GenC.gDynamicExPcd:
1020 Index = self._DynaPcdList_.index(PcdFromModule)
1021 self._DynaPcdList_[Index].Phase = PcdFromModule.Phase
1022 self._DynaPcdList_[Index].Type = PcdFromModule.Type
1023 for PcdFromModule in self._NonDynaPcdList_:
1024 # If a PCD is not listed in the DSC file, but binary INF files used by
1025 # this platform all (that use this PCD) list the PCD in a [PatchPcds]
1026 # section, AND all source INF files used by this platform the build
1027 # that use the PCD list the PCD in either a [Pcds] or [PatchPcds]
1028 # section, then the tools must NOT add the PCD to the Platform's PCD
1029 # Database; the build must assign the access method for this PCD as
1030 # PcdsPatchableInModule.
1031 if PcdFromModule not in self._DynaPcdList_:
1032 continue
1033 Index = self._DynaPcdList_.index(PcdFromModule)
1034 if PcdFromModule.IsFromDsc == False and \
1035 PcdFromModule.Type in TAB_PCDS_PATCHABLE_IN_MODULE and \
1036 PcdFromModule.IsFromBinaryInf == True and \
1037 self._DynaPcdList_[Index].IsFromBinaryInf == False:
1038 Index = self._DynaPcdList_.index(PcdFromModule)
1039 self._DynaPcdList_.remove (self._DynaPcdList_[Index])
1040
1041 # print out error information and break the build, if error found
1042 if len(NoDatumTypePcdList) > 0:
1043 NoDatumTypePcdListString = "\n\t\t".join(NoDatumTypePcdList)
1044 EdkLogger.error("build", AUTOGEN_ERROR, "PCD setting error",
1045 File=self.MetaFile,
1046 ExtraData="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"
1047 % NoDatumTypePcdListString)
1048 self._NonDynamicPcdList = self._NonDynaPcdList_
1049 self._DynamicPcdList = self._DynaPcdList_
1050 # If PCD is listed in a PcdsDynamicHii, PcdsDynamicExHii, PcdsDynamicHii or PcdsDynamicExHii
1051 # section, and the PCD is not used by any module that is listed in the DSC file, the build
1052 # provide a warning message.
1053 for PcdKey in self.Platform.Pcds.keys():
1054 Pcd = self.Platform.Pcds[PcdKey]
1055 if Pcd not in self._DynamicPcdList + PcdNotInDb and \
1056 Pcd.Type in [TAB_PCDS_DYNAMIC, TAB_PCDS_DYNAMIC_DEFAULT, TAB_PCDS_DYNAMIC_HII, TAB_PCDS_DYNAMIC_EX, TAB_PCDS_DYNAMIC_EX_DEFAULT, TAB_PCDS_DYNAMIC_EX_HII]:
1057 # Print warning message to let the developer make a determine.
1058 EdkLogger.warn("build",
1059 "A %s PCD listed in the DSC (%s.%s, %s) is not used by any module." \
1060 % (Pcd.Type, Pcd.TokenSpaceGuidCName, Pcd.TokenCName, self.Platform.MetaFile.Path),
1061 File=self.MetaFile, \
1062 ExtraData=None)
1063 #
1064 # Sort dynamic PCD list to:
1065 # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should
1066 # try to be put header of dynamicd List
1067 # 2) If PCD is HII type, the PCD item should be put after unicode type PCD
1068 #
1069 # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.
1070 #
1071 UnicodePcdArray = []
1072 HiiPcdArray = []
1073 OtherPcdArray = []
1074 VpdPcdDict = {}
1075 VpdFile = VpdInfoFile.VpdInfoFile()
1076 NeedProcessVpdMapFile = False
1077
1078 if (self.Workspace.ArchList[-1] == self.Arch):
1079 for Pcd in self._DynamicPcdList:
1080 # just pick the a value to determine whether is unicode string type
1081 Sku = Pcd.SkuInfoList[Pcd.SkuInfoList.keys()[0]]
1082 Sku.VpdOffset = Sku.VpdOffset.strip()
1083
1084 PcdValue = Sku.DefaultValue
1085 if Pcd.DatumType == 'VOID*' and PcdValue.startswith("L"):
1086 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
1087 UnicodePcdArray.append(Pcd)
1088 elif len(Sku.VariableName) > 0:
1089 # if found HII type PCD then insert to right of UnicodeIndex
1090 HiiPcdArray.append(Pcd)
1091 else:
1092 OtherPcdArray.append(Pcd)
1093 if Pcd.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:
1094 VpdPcdDict[(Pcd.TokenCName, Pcd.TokenSpaceGuidCName)] = Pcd
1095
1096 PlatformPcds = self.Platform.Pcds.keys()
1097 PlatformPcds.sort()
1098 #
1099 # Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.
1100 #
1101 for PcdKey in PlatformPcds:
1102 Pcd = self.Platform.Pcds[PcdKey]
1103 if Pcd.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD] and \
1104 PcdKey in VpdPcdDict:
1105 Pcd = VpdPcdDict[PcdKey]
1106 for (SkuName,Sku) in Pcd.SkuInfoList.items():
1107 Sku.VpdOffset = Sku.VpdOffset.strip()
1108 VpdFile.Add(Pcd, Sku.VpdOffset)
1109 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
1110 if not NeedProcessVpdMapFile and Sku.VpdOffset == "*":
1111 NeedProcessVpdMapFile = True
1112 if self.Platform.VpdToolGuid == None or self.Platform.VpdToolGuid == '':
1113 EdkLogger.error("Build", FILE_NOT_FOUND, \
1114 "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.")
1115
1116
1117 #
1118 # Fix the PCDs define in VPD PCD section that never referenced by module.
1119 # An example is PCD for signature usage.
1120 #
1121 for DscPcd in PlatformPcds:
1122 DscPcdEntry = self.Platform.Pcds[DscPcd]
1123 if DscPcdEntry.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:
1124 if not (self.Platform.VpdToolGuid == None or self.Platform.VpdToolGuid == ''):
1125 FoundFlag = False
1126 for VpdPcd in VpdFile._VpdArray.keys():
1127 # This PCD has been referenced by module
1128 if (VpdPcd.TokenSpaceGuidCName == DscPcdEntry.TokenSpaceGuidCName) and \
1129 (VpdPcd.TokenCName == DscPcdEntry.TokenCName):
1130 FoundFlag = True
1131
1132 # Not found, it should be signature
1133 if not FoundFlag :
1134 # just pick the a value to determine whether is unicode string type
1135 for (SkuName,Sku) in DscPcdEntry.SkuInfoList.items():
1136 Sku.VpdOffset = Sku.VpdOffset.strip()
1137
1138 # Need to iterate DEC pcd information to get the value & datumtype
1139 for eachDec in self.PackageList:
1140 for DecPcd in eachDec.Pcds:
1141 DecPcdEntry = eachDec.Pcds[DecPcd]
1142 if (DecPcdEntry.TokenSpaceGuidCName == DscPcdEntry.TokenSpaceGuidCName) and \
1143 (DecPcdEntry.TokenCName == DscPcdEntry.TokenCName):
1144 # Print warning message to let the developer make a determine.
1145 EdkLogger.warn("build", "Unreferenced vpd pcd used!",
1146 File=self.MetaFile, \
1147 ExtraData = "PCD: %s.%s used in the DSC file %s is unreferenced." \
1148 %(DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName, self.Platform.MetaFile.Path))
1149
1150 DscPcdEntry.DatumType = DecPcdEntry.DatumType
1151 DscPcdEntry.DefaultValue = DecPcdEntry.DefaultValue
1152 DscPcdEntry.TokenValue = DecPcdEntry.TokenValue
1153 DscPcdEntry.TokenSpaceGuidValue = eachDec.Guids[DecPcdEntry.TokenSpaceGuidCName]
1154 # Only fix the value while no value provided in DSC file.
1155 if (Sku.DefaultValue == "" or Sku.DefaultValue==None):
1156 DscPcdEntry.SkuInfoList[DscPcdEntry.SkuInfoList.keys()[0]].DefaultValue = DecPcdEntry.DefaultValue
1157
1158 if DscPcdEntry not in self._DynamicPcdList:
1159 self._DynamicPcdList.append(DscPcdEntry)
1160 # Sku = DscPcdEntry.SkuInfoList[DscPcdEntry.SkuInfoList.keys()[0]]
1161 Sku.VpdOffset = Sku.VpdOffset.strip()
1162 PcdValue = Sku.DefaultValue
1163 VpdFile.Add(DscPcdEntry, Sku.VpdOffset)
1164 if not NeedProcessVpdMapFile and Sku.VpdOffset == "*":
1165 NeedProcessVpdMapFile = True
1166 if DscPcdEntry.DatumType == 'VOID*' and PcdValue.startswith("L"):
1167 UnicodePcdArray.append(DscPcdEntry)
1168 elif len(Sku.VariableName) > 0:
1169 HiiPcdArray.append(DscPcdEntry)
1170 else:
1171 OtherPcdArray.append(DscPcdEntry)
1172
1173 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
1174
1175
1176
1177 if (self.Platform.FlashDefinition == None or self.Platform.FlashDefinition == '') and \
1178 VpdFile.GetCount() != 0:
1179 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE,
1180 "Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD." % str(self.Platform.MetaFile))
1181
1182 if VpdFile.GetCount() != 0:
1183 DscTimeStamp = self.Platform.MetaFile.TimeStamp
1184 FvPath = os.path.join(self.BuildDir, "FV")
1185 if not os.path.exists(FvPath):
1186 try:
1187 os.makedirs(FvPath)
1188 except:
1189 EdkLogger.error("build", FILE_WRITE_FAILURE, "Fail to create FV folder under %s" % self.BuildDir)
1190
1191
1192 VpdFilePath = os.path.join(FvPath, "%s.txt" % self.Platform.VpdToolGuid)
1193
1194
1195 if not os.path.exists(VpdFilePath) or os.path.getmtime(VpdFilePath) < DscTimeStamp:
1196 VpdFile.Write(VpdFilePath)
1197
1198 # retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.
1199 BPDGToolName = None
1200 for ToolDef in self.ToolDefinition.values():
1201 if ToolDef.has_key("GUID") and ToolDef["GUID"] == self.Platform.VpdToolGuid:
1202 if not ToolDef.has_key("PATH"):
1203 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "PATH attribute was not provided for BPDG guid tool %s in tools_def.txt" % self.Platform.VpdToolGuid)
1204 BPDGToolName = ToolDef["PATH"]
1205 break
1206 # Call third party GUID BPDG tool.
1207 if BPDGToolName != None:
1208 VpdInfoFile.CallExtenalBPDGTool(BPDGToolName, VpdFilePath)
1209 else:
1210 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.")
1211
1212 # Process VPD map file generated by third party BPDG tool
1213 if NeedProcessVpdMapFile:
1214 VpdMapFilePath = os.path.join(self.BuildDir, "FV", "%s.map" % self.Platform.VpdToolGuid)
1215 if os.path.exists(VpdMapFilePath):
1216 VpdFile.Read(VpdMapFilePath)
1217
1218 # Fixup "*" offset
1219 for Pcd in self._DynamicPcdList:
1220 # just pick the a value to determine whether is unicode string type
1221 i = 0
1222 for (SkuName,Sku) in Pcd.SkuInfoList.items():
1223 if Sku.VpdOffset == "*":
1224 Sku.VpdOffset = VpdFile.GetOffset(Pcd)[i].strip()
1225 i += 1
1226 else:
1227 EdkLogger.error("build", FILE_READ_FAILURE, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath)
1228
1229 # Delete the DynamicPcdList At the last time enter into this function
1230 del self._DynamicPcdList[:]
1231 self._DynamicPcdList.extend(UnicodePcdArray)
1232 self._DynamicPcdList.extend(HiiPcdArray)
1233 self._DynamicPcdList.extend(OtherPcdArray)
1234 self.AllPcdList = self._NonDynamicPcdList + self._DynamicPcdList
1235
1236 ## Return the platform build data object
1237 def _GetPlatform(self):
1238 if self._Platform == None:
1239 self._Platform = self.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]
1240 return self._Platform
1241
1242 ## Return platform name
1243 def _GetName(self):
1244 return self.Platform.PlatformName
1245
1246 ## Return the meta file GUID
1247 def _GetGuid(self):
1248 return self.Platform.Guid
1249
1250 ## Return the platform version
1251 def _GetVersion(self):
1252 return self.Platform.Version
1253
1254 ## Return the FDF file name
1255 def _GetFdfFile(self):
1256 if self._FdfFile == None:
1257 if self.Workspace.FdfFile != "":
1258 self._FdfFile= path.join(self.WorkspaceDir, self.Workspace.FdfFile)
1259 else:
1260 self._FdfFile = ''
1261 return self._FdfFile
1262
1263 ## Return the build output directory platform specifies
1264 def _GetOutputDir(self):
1265 return self.Platform.OutputDirectory
1266
1267 ## Return the directory to store all intermediate and final files built
1268 def _GetBuildDir(self):
1269 if self._BuildDir == None:
1270 if os.path.isabs(self.OutputDir):
1271 self._BuildDir = path.join(
1272 path.abspath(self.OutputDir),
1273 self.BuildTarget + "_" + self.ToolChain,
1274 )
1275 else:
1276 self._BuildDir = path.join(
1277 self.WorkspaceDir,
1278 self.OutputDir,
1279 self.BuildTarget + "_" + self.ToolChain,
1280 )
1281 return self._BuildDir
1282
1283 ## Return directory of platform makefile
1284 #
1285 # @retval string Makefile directory
1286 #
1287 def _GetMakeFileDir(self):
1288 if self._MakeFileDir == None:
1289 self._MakeFileDir = path.join(self.BuildDir, self.Arch)
1290 return self._MakeFileDir
1291
1292 ## Return build command string
1293 #
1294 # @retval string Build command string
1295 #
1296 def _GetBuildCommand(self):
1297 if self._BuildCommand == None:
1298 self._BuildCommand = []
1299 if "MAKE" in self.ToolDefinition and "PATH" in self.ToolDefinition["MAKE"]:
1300 self._BuildCommand += SplitOption(self.ToolDefinition["MAKE"]["PATH"])
1301 if "FLAGS" in self.ToolDefinition["MAKE"]:
1302 NewOption = self.ToolDefinition["MAKE"]["FLAGS"].strip()
1303 if NewOption != '':
1304 self._BuildCommand += SplitOption(NewOption)
1305 return self._BuildCommand
1306
1307 ## Get tool chain definition
1308 #
1309 # Get each tool defition for given tool chain from tools_def.txt and platform
1310 #
1311 def _GetToolDefinition(self):
1312 if self._ToolDefinitions == None:
1313 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDictionary
1314 if TAB_TOD_DEFINES_COMMAND_TYPE not in self.Workspace.ToolDef.ToolsDefTxtDatabase:
1315 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "No tools found in configuration",
1316 ExtraData="[%s]" % self.MetaFile)
1317 self._ToolDefinitions = {}
1318 DllPathList = set()
1319 for Def in ToolDefinition:
1320 Target, Tag, Arch, Tool, Attr = Def.split("_")
1321 if Target != self.BuildTarget or Tag != self.ToolChain or Arch != self.Arch:
1322 continue
1323
1324 Value = ToolDefinition[Def]
1325 # don't record the DLL
1326 if Attr == "DLL":
1327 DllPathList.add(Value)
1328 continue
1329
1330 if Tool not in self._ToolDefinitions:
1331 self._ToolDefinitions[Tool] = {}
1332 self._ToolDefinitions[Tool][Attr] = Value
1333
1334 ToolsDef = ''
1335 MakePath = ''
1336 if GlobalData.gOptions.SilentMode and "MAKE" in self._ToolDefinitions:
1337 if "FLAGS" not in self._ToolDefinitions["MAKE"]:
1338 self._ToolDefinitions["MAKE"]["FLAGS"] = ""
1339 self._ToolDefinitions["MAKE"]["FLAGS"] += " -s"
1340 MakeFlags = ''
1341 for Tool in self._ToolDefinitions:
1342 for Attr in self._ToolDefinitions[Tool]:
1343 Value = self._ToolDefinitions[Tool][Attr]
1344 if Tool in self.BuildOption and Attr in self.BuildOption[Tool]:
1345 # check if override is indicated
1346 if self.BuildOption[Tool][Attr].startswith('='):
1347 Value = self.BuildOption[Tool][Attr][1:]
1348 else:
1349 Value += " " + self.BuildOption[Tool][Attr]
1350
1351 if Attr == "PATH":
1352 # Don't put MAKE definition in the file
1353 if Tool == "MAKE":
1354 MakePath = Value
1355 else:
1356 ToolsDef += "%s = %s\n" % (Tool, Value)
1357 elif Attr != "DLL":
1358 # Don't put MAKE definition in the file
1359 if Tool == "MAKE":
1360 if Attr == "FLAGS":
1361 MakeFlags = Value
1362 else:
1363 ToolsDef += "%s_%s = %s\n" % (Tool, Attr, Value)
1364 ToolsDef += "\n"
1365
1366 SaveFileOnChange(self.ToolDefinitionFile, ToolsDef)
1367 for DllPath in DllPathList:
1368 os.environ["PATH"] = DllPath + os.pathsep + os.environ["PATH"]
1369 os.environ["MAKE_FLAGS"] = MakeFlags
1370
1371 return self._ToolDefinitions
1372
1373 ## Return the paths of tools
1374 def _GetToolDefFile(self):
1375 if self._ToolDefFile == None:
1376 self._ToolDefFile = os.path.join(self.MakeFileDir, "TOOLS_DEF." + self.Arch)
1377 return self._ToolDefFile
1378
1379 ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
1380 def _GetToolChainFamily(self):
1381 if self._ToolChainFamily == None:
1382 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase
1383 if TAB_TOD_DEFINES_FAMILY not in ToolDefinition \
1384 or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_FAMILY] \
1385 or not ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]:
1386 EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1387 % self.ToolChain)
1388 self._ToolChainFamily = "MSFT"
1389 else:
1390 self._ToolChainFamily = ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]
1391 return self._ToolChainFamily
1392
1393 def _GetBuildRuleFamily(self):
1394 if self._BuildRuleFamily == None:
1395 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase
1396 if TAB_TOD_DEFINES_BUILDRULEFAMILY not in ToolDefinition \
1397 or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY] \
1398 or not ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]:
1399 EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1400 % self.ToolChain)
1401 self._BuildRuleFamily = "MSFT"
1402 else:
1403 self._BuildRuleFamily = ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]
1404 return self._BuildRuleFamily
1405
1406 ## Return the build options specific for all modules in this platform
1407 def _GetBuildOptions(self):
1408 if self._BuildOption == None:
1409 self._BuildOption = self._ExpandBuildOption(self.Platform.BuildOptions)
1410 return self._BuildOption
1411
1412 ## Return the build options specific for EDK modules in this platform
1413 def _GetEdkBuildOptions(self):
1414 if self._EdkBuildOption == None:
1415 self._EdkBuildOption = self._ExpandBuildOption(self.Platform.BuildOptions, EDK_NAME)
1416 return self._EdkBuildOption
1417
1418 ## Return the build options specific for EDKII modules in this platform
1419 def _GetEdkIIBuildOptions(self):
1420 if self._EdkIIBuildOption == None:
1421 self._EdkIIBuildOption = self._ExpandBuildOption(self.Platform.BuildOptions, EDKII_NAME)
1422 return self._EdkIIBuildOption
1423
1424 ## Parse build_rule.txt in $(WORKSPACE)/Conf/build_rule.txt
1425 #
1426 # @retval BuildRule object
1427 #
1428 def _GetBuildRule(self):
1429 if self._BuildRule == None:
1430 BuildRuleFile = None
1431 if TAB_TAT_DEFINES_BUILD_RULE_CONF in self.Workspace.TargetTxt.TargetTxtDictionary:
1432 BuildRuleFile = self.Workspace.TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_BUILD_RULE_CONF]
1433 if BuildRuleFile in [None, '']:
1434 BuildRuleFile = gBuildRuleFile
1435 self._BuildRule = BuildRule(BuildRuleFile)
1436 if self._BuildRule._FileVersion == "":
1437 self._BuildRule._FileVersion = AutoGenReqBuildRuleVerNum
1438 else:
1439 if self._BuildRule._FileVersion < AutoGenReqBuildRuleVerNum :
1440 # If Build Rule's version is less than the version number required by the tools, halting the build.
1441 EdkLogger.error("build", AUTOGEN_ERROR,
1442 ExtraData="The version number [%s] of build_rule.txt is less than the version number required by the AutoGen.(the minimum required version number is [%s])"\
1443 % (self._BuildRule._FileVersion, AutoGenReqBuildRuleVerNum))
1444
1445 return self._BuildRule
1446
1447 ## Summarize the packages used by modules in this platform
1448 def _GetPackageList(self):
1449 if self._PackageList == None:
1450 self._PackageList = set()
1451 for La in self.LibraryAutoGenList:
1452 self._PackageList.update(La.DependentPackageList)
1453 for Ma in self.ModuleAutoGenList:
1454 self._PackageList.update(Ma.DependentPackageList)
1455 #Collect package set information from INF of FDF
1456 PkgSet = set()
1457 for ModuleFile in self._AsBuildModuleList:
1458 if ModuleFile in self.Platform.Modules:
1459 continue
1460 ModuleData = self.BuildDatabase[ModuleFile, self.Arch, self.BuildTarget, self.ToolChain]
1461 PkgSet.update(ModuleData.Packages)
1462 self._PackageList = list(self._PackageList) + list (PkgSet)
1463 return self._PackageList
1464
1465 def _GetNonDynamicPcdDict(self):
1466 if self._NonDynamicPcdDict:
1467 return self._NonDynamicPcdDict
1468 for Pcd in self.NonDynamicPcdList:
1469 self._NonDynamicPcdDict[(Pcd.TokenCName,Pcd.TokenSpaceGuidCName)] = Pcd
1470 return self._NonDynamicPcdDict
1471
1472 ## Get list of non-dynamic PCDs
1473 def _GetNonDynamicPcdList(self):
1474 if self._NonDynamicPcdList == None:
1475 self.CollectPlatformDynamicPcds()
1476 return self._NonDynamicPcdList
1477
1478 ## Get list of dynamic PCDs
1479 def _GetDynamicPcdList(self):
1480 if self._DynamicPcdList == None:
1481 self.CollectPlatformDynamicPcds()
1482 return self._DynamicPcdList
1483
1484 ## Generate Token Number for all PCD
1485 def _GetPcdTokenNumbers(self):
1486 if self._PcdTokenNumber == None:
1487 self._PcdTokenNumber = sdict()
1488 TokenNumber = 1
1489 #
1490 # Make the Dynamic and DynamicEx PCD use within different TokenNumber area.
1491 # Such as:
1492 #
1493 # Dynamic PCD:
1494 # TokenNumber 0 ~ 10
1495 # DynamicEx PCD:
1496 # TokeNumber 11 ~ 20
1497 #
1498 for Pcd in self.DynamicPcdList:
1499 if Pcd.Phase == "PEI":
1500 if Pcd.Type in ["Dynamic", "DynamicDefault", "DynamicVpd", "DynamicHii"]:
1501 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
1502 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
1503 TokenNumber += 1
1504
1505 for Pcd in self.DynamicPcdList:
1506 if Pcd.Phase == "PEI":
1507 if Pcd.Type in ["DynamicEx", "DynamicExDefault", "DynamicExVpd", "DynamicExHii"]:
1508 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
1509 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
1510 TokenNumber += 1
1511
1512 for Pcd in self.DynamicPcdList:
1513 if Pcd.Phase == "DXE":
1514 if Pcd.Type in ["Dynamic", "DynamicDefault", "DynamicVpd", "DynamicHii"]:
1515 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
1516 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
1517 TokenNumber += 1
1518
1519 for Pcd in self.DynamicPcdList:
1520 if Pcd.Phase == "DXE":
1521 if Pcd.Type in ["DynamicEx", "DynamicExDefault", "DynamicExVpd", "DynamicExHii"]:
1522 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
1523 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
1524 TokenNumber += 1
1525
1526 for Pcd in self.NonDynamicPcdList:
1527 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
1528 TokenNumber += 1
1529 return self._PcdTokenNumber
1530
1531 ## Summarize ModuleAutoGen objects of all modules/libraries to be built for this platform
1532 def _GetAutoGenObjectList(self):
1533 self._ModuleAutoGenList = []
1534 self._LibraryAutoGenList = []
1535 for ModuleFile in self.Platform.Modules:
1536 Ma = ModuleAutoGen(
1537 self.Workspace,
1538 ModuleFile,
1539 self.BuildTarget,
1540 self.ToolChain,
1541 self.Arch,
1542 self.MetaFile
1543 )
1544 if Ma not in self._ModuleAutoGenList:
1545 self._ModuleAutoGenList.append(Ma)
1546 for La in Ma.LibraryAutoGenList:
1547 if La not in self._LibraryAutoGenList:
1548 self._LibraryAutoGenList.append(La)
1549 if Ma not in La._ReferenceModules:
1550 La._ReferenceModules.append(Ma)
1551
1552 ## Summarize ModuleAutoGen objects of all modules to be built for this platform
1553 def _GetModuleAutoGenList(self):
1554 if self._ModuleAutoGenList == None:
1555 self._GetAutoGenObjectList()
1556 return self._ModuleAutoGenList
1557
1558 ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
1559 def _GetLibraryAutoGenList(self):
1560 if self._LibraryAutoGenList == None:
1561 self._GetAutoGenObjectList()
1562 return self._LibraryAutoGenList
1563
1564 ## Test if a module is supported by the platform
1565 #
1566 # An error will be raised directly if the module or its arch is not supported
1567 # by the platform or current configuration
1568 #
1569 def ValidModule(self, Module):
1570 return Module in self.Platform.Modules or Module in self.Platform.LibraryInstances \
1571 or Module in self._AsBuildModuleList
1572
1573 ## Resolve the library classes in a module to library instances
1574 #
1575 # This method will not only resolve library classes but also sort the library
1576 # instances according to the dependency-ship.
1577 #
1578 # @param Module The module from which the library classes will be resolved
1579 #
1580 # @retval library_list List of library instances sorted
1581 #
1582 def ApplyLibraryInstance(self, Module):
1583 ModuleType = Module.ModuleType
1584
1585 # for overridding library instances with module specific setting
1586 PlatformModule = self.Platform.Modules[str(Module)]
1587
1588 # add forced library instances (specified under LibraryClasses sections)
1589 #
1590 # If a module has a MODULE_TYPE of USER_DEFINED,
1591 # do not link in NULL library class instances from the global [LibraryClasses.*] sections.
1592 #
1593 if Module.ModuleType != SUP_MODULE_USER_DEFINED:
1594 for LibraryClass in self.Platform.LibraryClasses.GetKeys():
1595 if LibraryClass.startswith("NULL") and self.Platform.LibraryClasses[LibraryClass, Module.ModuleType]:
1596 Module.LibraryClasses[LibraryClass] = self.Platform.LibraryClasses[LibraryClass, Module.ModuleType]
1597
1598 # add forced library instances (specified in module overrides)
1599 for LibraryClass in PlatformModule.LibraryClasses:
1600 if LibraryClass.startswith("NULL"):
1601 Module.LibraryClasses[LibraryClass] = PlatformModule.LibraryClasses[LibraryClass]
1602
1603 # EdkII module
1604 LibraryConsumerList = [Module]
1605 Constructor = []
1606 ConsumedByList = sdict()
1607 LibraryInstance = sdict()
1608
1609 EdkLogger.verbose("")
1610 EdkLogger.verbose("Library instances of module [%s] [%s]:" % (str(Module), self.Arch))
1611 while len(LibraryConsumerList) > 0:
1612 M = LibraryConsumerList.pop()
1613 for LibraryClassName in M.LibraryClasses:
1614 if LibraryClassName not in LibraryInstance:
1615 # override library instance for this module
1616 if LibraryClassName in PlatformModule.LibraryClasses:
1617 LibraryPath = PlatformModule.LibraryClasses[LibraryClassName]
1618 else:
1619 LibraryPath = self.Platform.LibraryClasses[LibraryClassName, ModuleType]
1620 if LibraryPath == None or LibraryPath == "":
1621 LibraryPath = M.LibraryClasses[LibraryClassName]
1622 if LibraryPath == None or LibraryPath == "":
1623 EdkLogger.error("build", RESOURCE_NOT_AVAILABLE,
1624 "Instance of library class [%s] is not found" % LibraryClassName,
1625 File=self.MetaFile,
1626 ExtraData="in [%s] [%s]\n\tconsumed by module [%s]" % (str(M), self.Arch, str(Module)))
1627
1628 LibraryModule = self.BuildDatabase[LibraryPath, self.Arch, self.BuildTarget, self.ToolChain]
1629 # for those forced library instance (NULL library), add a fake library class
1630 if LibraryClassName.startswith("NULL"):
1631 LibraryModule.LibraryClass.append(LibraryClassObject(LibraryClassName, [ModuleType]))
1632 elif LibraryModule.LibraryClass == None \
1633 or len(LibraryModule.LibraryClass) == 0 \
1634 or (ModuleType != 'USER_DEFINED'
1635 and ModuleType not in LibraryModule.LibraryClass[0].SupModList):
1636 # only USER_DEFINED can link against any library instance despite of its SupModList
1637 EdkLogger.error("build", OPTION_MISSING,
1638 "Module type [%s] is not supported by library instance [%s]" \
1639 % (ModuleType, LibraryPath), File=self.MetaFile,
1640 ExtraData="consumed by [%s]" % str(Module))
1641
1642 LibraryInstance[LibraryClassName] = LibraryModule
1643 LibraryConsumerList.append(LibraryModule)
1644 EdkLogger.verbose("\t" + str(LibraryClassName) + " : " + str(LibraryModule))
1645 else:
1646 LibraryModule = LibraryInstance[LibraryClassName]
1647
1648 if LibraryModule == None:
1649 continue
1650
1651 if LibraryModule.ConstructorList != [] and LibraryModule not in Constructor:
1652 Constructor.append(LibraryModule)
1653
1654 if LibraryModule not in ConsumedByList:
1655 ConsumedByList[LibraryModule] = []
1656 # don't add current module itself to consumer list
1657 if M != Module:
1658 if M in ConsumedByList[LibraryModule]:
1659 continue
1660 ConsumedByList[LibraryModule].append(M)
1661 #
1662 # Initialize the sorted output list to the empty set
1663 #
1664 SortedLibraryList = []
1665 #
1666 # Q <- Set of all nodes with no incoming edges
1667 #
1668 LibraryList = [] #LibraryInstance.values()
1669 Q = []
1670 for LibraryClassName in LibraryInstance:
1671 M = LibraryInstance[LibraryClassName]
1672 LibraryList.append(M)
1673 if ConsumedByList[M] == []:
1674 Q.append(M)
1675
1676 #
1677 # start the DAG algorithm
1678 #
1679 while True:
1680 EdgeRemoved = True
1681 while Q == [] and EdgeRemoved:
1682 EdgeRemoved = False
1683 # for each node Item with a Constructor
1684 for Item in LibraryList:
1685 if Item not in Constructor:
1686 continue
1687 # for each Node without a constructor with an edge e from Item to Node
1688 for Node in ConsumedByList[Item]:
1689 if Node in Constructor:
1690 continue
1691 # remove edge e from the graph if Node has no constructor
1692 ConsumedByList[Item].remove(Node)
1693 EdgeRemoved = True
1694 if ConsumedByList[Item] == []:
1695 # insert Item into Q
1696 Q.insert(0, Item)
1697 break
1698 if Q != []:
1699 break
1700 # DAG is done if there's no more incoming edge for all nodes
1701 if Q == []:
1702 break
1703
1704 # remove node from Q
1705 Node = Q.pop()
1706 # output Node
1707 SortedLibraryList.append(Node)
1708
1709 # for each node Item with an edge e from Node to Item do
1710 for Item in LibraryList:
1711 if Node not in ConsumedByList[Item]:
1712 continue
1713 # remove edge e from the graph
1714 ConsumedByList[Item].remove(Node)
1715
1716 if ConsumedByList[Item] != []:
1717 continue
1718 # insert Item into Q, if Item has no other incoming edges
1719 Q.insert(0, Item)
1720
1721 #
1722 # if any remaining node Item in the graph has a constructor and an incoming edge, then the graph has a cycle
1723 #
1724 for Item in LibraryList:
1725 if ConsumedByList[Item] != [] and Item in Constructor and len(Constructor) > 1:
1726 ErrorMessage = "\tconsumed by " + "\n\tconsumed by ".join([str(L) for L in ConsumedByList[Item]])
1727 EdkLogger.error("build", BUILD_ERROR, 'Library [%s] with constructors has a cycle' % str(Item),
1728 ExtraData=ErrorMessage, File=self.MetaFile)
1729 if Item not in SortedLibraryList:
1730 SortedLibraryList.append(Item)
1731
1732 #
1733 # Build the list of constructor and destructir names
1734 # The DAG Topo sort produces the destructor order, so the list of constructors must generated in the reverse order
1735 #
1736 SortedLibraryList.reverse()
1737 return SortedLibraryList
1738
1739
1740 ## Override PCD setting (type, value, ...)
1741 #
1742 # @param ToPcd The PCD to be overrided
1743 # @param FromPcd The PCD overrideing from
1744 #
1745 def _OverridePcd(self, ToPcd, FromPcd, Module=""):
1746 #
1747 # in case there's PCDs coming from FDF file, which have no type given.
1748 # at this point, ToPcd.Type has the type found from dependent
1749 # package
1750 #
1751 if FromPcd != None:
1752 if ToPcd.Pending and FromPcd.Type not in [None, '']:
1753 ToPcd.Type = FromPcd.Type
1754 elif (ToPcd.Type not in [None, '']) and (FromPcd.Type not in [None, ''])\
1755 and (ToPcd.Type != FromPcd.Type) and (ToPcd.Type in FromPcd.Type):
1756 if ToPcd.Type.strip() == "DynamicEx":
1757 ToPcd.Type = FromPcd.Type
1758 elif ToPcd.Type not in [None, ''] and FromPcd.Type not in [None, ''] \
1759 and ToPcd.Type != FromPcd.Type:
1760 EdkLogger.error("build", OPTION_CONFLICT, "Mismatched PCD type",
1761 ExtraData="%s.%s is defined as [%s] in module %s, but as [%s] in platform."\
1762 % (ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName,
1763 ToPcd.Type, Module, FromPcd.Type),
1764 File=self.MetaFile)
1765
1766 if FromPcd.MaxDatumSize not in [None, '']:
1767 ToPcd.MaxDatumSize = FromPcd.MaxDatumSize
1768 if FromPcd.DefaultValue not in [None, '']:
1769 ToPcd.DefaultValue = FromPcd.DefaultValue
1770 if FromPcd.TokenValue not in [None, '']:
1771 ToPcd.TokenValue = FromPcd.TokenValue
1772 if FromPcd.MaxDatumSize not in [None, '']:
1773 ToPcd.MaxDatumSize = FromPcd.MaxDatumSize
1774 if FromPcd.DatumType not in [None, '']:
1775 ToPcd.DatumType = FromPcd.DatumType
1776 if FromPcd.SkuInfoList not in [None, '', []]:
1777 ToPcd.SkuInfoList = FromPcd.SkuInfoList
1778
1779 # check the validation of datum
1780 IsValid, Cause = CheckPcdDatum(ToPcd.DatumType, ToPcd.DefaultValue)
1781 if not IsValid:
1782 EdkLogger.error('build', FORMAT_INVALID, Cause, File=self.MetaFile,
1783 ExtraData="%s.%s" % (ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName))
1784
1785 if ToPcd.DatumType == "VOID*" and ToPcd.MaxDatumSize in ['', None]:
1786 EdkLogger.debug(EdkLogger.DEBUG_9, "No MaxDatumSize specified for PCD %s.%s" \
1787 % (ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName))
1788 Value = ToPcd.DefaultValue
1789 if Value in [None, '']:
1790 ToPcd.MaxDatumSize = '1'
1791 elif Value[0] == 'L':
1792 ToPcd.MaxDatumSize = str((len(Value) - 2) * 2)
1793 elif Value[0] == '{':
1794 ToPcd.MaxDatumSize = str(len(Value.split(',')))
1795 else:
1796 ToPcd.MaxDatumSize = str(len(Value) - 1)
1797
1798 # apply default SKU for dynamic PCDS if specified one is not available
1799 if (ToPcd.Type in PCD_DYNAMIC_TYPE_LIST or ToPcd.Type in PCD_DYNAMIC_EX_TYPE_LIST) \
1800 and ToPcd.SkuInfoList in [None, {}, '']:
1801 if self.Platform.SkuName in self.Platform.SkuIds:
1802 SkuName = self.Platform.SkuName
1803 else:
1804 SkuName = 'DEFAULT'
1805 ToPcd.SkuInfoList = {
1806 SkuName : SkuInfoClass(SkuName, self.Platform.SkuIds[SkuName], '', '', '', '', '', ToPcd.DefaultValue)
1807 }
1808
1809 ## Apply PCD setting defined platform to a module
1810 #
1811 # @param Module The module from which the PCD setting will be overrided
1812 #
1813 # @retval PCD_list The list PCDs with settings from platform
1814 #
1815 def ApplyPcdSetting(self, Module, Pcds):
1816 # for each PCD in module
1817 for Name,Guid in Pcds:
1818 PcdInModule = Pcds[Name,Guid]
1819 # find out the PCD setting in platform
1820 if (Name,Guid) in self.Platform.Pcds:
1821 PcdInPlatform = self.Platform.Pcds[Name,Guid]
1822 else:
1823 PcdInPlatform = None
1824 # then override the settings if any
1825 self._OverridePcd(PcdInModule, PcdInPlatform, Module)
1826 # resolve the VariableGuid value
1827 for SkuId in PcdInModule.SkuInfoList:
1828 Sku = PcdInModule.SkuInfoList[SkuId]
1829 if Sku.VariableGuid == '': continue
1830 Sku.VariableGuidValue = GuidValue(Sku.VariableGuid, self.PackageList)
1831 if Sku.VariableGuidValue == None:
1832 PackageList = "\n\t".join([str(P) for P in self.PackageList])
1833 EdkLogger.error(
1834 'build',
1835 RESOURCE_NOT_AVAILABLE,
1836 "Value of GUID [%s] is not found in" % Sku.VariableGuid,
1837 ExtraData=PackageList + "\n\t(used with %s.%s from module %s)" \
1838 % (Guid, Name, str(Module)),
1839 File=self.MetaFile
1840 )
1841
1842 # override PCD settings with module specific setting
1843 if Module in self.Platform.Modules:
1844 PlatformModule = self.Platform.Modules[str(Module)]
1845 for Key in PlatformModule.Pcds:
1846 if Key in Pcds:
1847 self._OverridePcd(Pcds[Key], PlatformModule.Pcds[Key], Module)
1848 return Pcds.values()
1849
1850 ## Resolve library names to library modules
1851 #
1852 # (for Edk.x modules)
1853 #
1854 # @param Module The module from which the library names will be resolved
1855 #
1856 # @retval library_list The list of library modules
1857 #
1858 def ResolveLibraryReference(self, Module):
1859 EdkLogger.verbose("")
1860 EdkLogger.verbose("Library instances of module [%s] [%s]:" % (str(Module), self.Arch))
1861 LibraryConsumerList = [Module]
1862
1863 # "CompilerStub" is a must for Edk modules
1864 if Module.Libraries:
1865 Module.Libraries.append("CompilerStub")
1866 LibraryList = []
1867 while len(LibraryConsumerList) > 0:
1868 M = LibraryConsumerList.pop()
1869 for LibraryName in M.Libraries:
1870 Library = self.Platform.LibraryClasses[LibraryName, ':dummy:']
1871 if Library == None:
1872 for Key in self.Platform.LibraryClasses.data.keys():
1873 if LibraryName.upper() == Key.upper():
1874 Library = self.Platform.LibraryClasses[Key, ':dummy:']
1875 break
1876 if Library == None:
1877 EdkLogger.warn("build", "Library [%s] is not found" % LibraryName, File=str(M),
1878 ExtraData="\t%s [%s]" % (str(Module), self.Arch))
1879 continue
1880
1881 if Library not in LibraryList:
1882 LibraryList.append(Library)
1883 LibraryConsumerList.append(Library)
1884 EdkLogger.verbose("\t" + LibraryName + " : " + str(Library) + ' ' + str(type(Library)))
1885 return LibraryList
1886
1887 ## Calculate the priority value of the build option
1888 #
1889 # @param Key Build option definition contain: TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
1890 #
1891 # @retval Value Priority value based on the priority list.
1892 #
1893 def CalculatePriorityValue(self, Key):
1894 Target, ToolChain, Arch, CommandType, Attr = Key.split('_')
1895 PriorityValue = 0x11111
1896 if Target == "*":
1897 PriorityValue &= 0x01111
1898 if ToolChain == "*":
1899 PriorityValue &= 0x10111
1900 if Arch == "*":
1901 PriorityValue &= 0x11011
1902 if CommandType == "*":
1903 PriorityValue &= 0x11101
1904 if Attr == "*":
1905 PriorityValue &= 0x11110
1906
1907 return self.PrioList["0x%0.5x"%PriorityValue]
1908
1909
1910 ## Expand * in build option key
1911 #
1912 # @param Options Options to be expanded
1913 #
1914 # @retval options Options expanded
1915 #
1916 def _ExpandBuildOption(self, Options, ModuleStyle=None):
1917 BuildOptions = {}
1918 FamilyMatch = False
1919 FamilyIsNull = True
1920
1921 OverrideList = {}
1922 #
1923 # Construct a list contain the build options which need override.
1924 #
1925 for Key in Options:
1926 #
1927 # Key[0] -- tool family
1928 # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
1929 #
1930 if Key[0] == self.BuildRuleFamily :
1931 Target, ToolChain, Arch, CommandType, Attr = Key[1].split('_')
1932 if Target == self.BuildTarget or Target == "*":
1933 if ToolChain == self.ToolChain or ToolChain == "*":
1934 if Arch == self.Arch or Arch == "*":
1935 if Options[Key].startswith("="):
1936 if OverrideList.get(Key[1]) != None:
1937 OverrideList.pop(Key[1])
1938 OverrideList[Key[1]] = Options[Key]
1939
1940 #
1941 # Use the highest priority value.
1942 #
1943 if (len(OverrideList) >= 2):
1944 KeyList = OverrideList.keys()
1945 for Index in range(len(KeyList)):
1946 NowKey = KeyList[Index]
1947 Target1, ToolChain1, Arch1, CommandType1, Attr1 = NowKey.split("_")
1948 for Index1 in range(len(KeyList) - Index - 1):
1949 NextKey = KeyList[Index1 + Index + 1]
1950 #
1951 # Compare two Key, if one is included by another, choose the higher priority one
1952 #
1953 Target2, ToolChain2, Arch2, CommandType2, Attr2 = NextKey.split("_")
1954 if Target1 == Target2 or Target1 == "*" or Target2 == "*":
1955 if ToolChain1 == ToolChain2 or ToolChain1 == "*" or ToolChain2 == "*":
1956 if Arch1 == Arch2 or Arch1 == "*" or Arch2 == "*":
1957 if CommandType1 == CommandType2 or CommandType1 == "*" or CommandType2 == "*":
1958 if Attr1 == Attr2 or Attr1 == "*" or Attr2 == "*":
1959 if self.CalculatePriorityValue(NowKey) > self.CalculatePriorityValue(NextKey):
1960 if Options.get((self.BuildRuleFamily, NextKey)) != None:
1961 Options.pop((self.BuildRuleFamily, NextKey))
1962 else:
1963 if Options.get((self.BuildRuleFamily, NowKey)) != None:
1964 Options.pop((self.BuildRuleFamily, NowKey))
1965
1966
1967 for Key in Options:
1968 if ModuleStyle != None and len (Key) > 2:
1969 # Check Module style is EDK or EDKII.
1970 # Only append build option for the matched style module.
1971 if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:
1972 continue
1973 elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:
1974 continue
1975 Family = Key[0]
1976 Target, Tag, Arch, Tool, Attr = Key[1].split("_")
1977 # if tool chain family doesn't match, skip it
1978 if Tool in self.ToolDefinition and Family != "":
1979 FamilyIsNull = False
1980 if self.ToolDefinition[Tool].get(TAB_TOD_DEFINES_BUILDRULEFAMILY, "") != "":
1981 if Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_BUILDRULEFAMILY]:
1982 continue
1983 elif Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_FAMILY]:
1984 continue
1985 FamilyMatch = True
1986 # expand any wildcard
1987 if Target == "*" or Target == self.BuildTarget:
1988 if Tag == "*" or Tag == self.ToolChain:
1989 if Arch == "*" or Arch == self.Arch:
1990 if Tool not in BuildOptions:
1991 BuildOptions[Tool] = {}
1992 if Attr != "FLAGS" or Attr not in BuildOptions[Tool]:
1993 BuildOptions[Tool][Attr] = Options[Key]
1994 else:
1995 # append options for the same tool
1996 BuildOptions[Tool][Attr] += " " + Options[Key]
1997 # Build Option Family has been checked, which need't to be checked again for family.
1998 if FamilyMatch or FamilyIsNull:
1999 return BuildOptions
2000
2001 for Key in Options:
2002 if ModuleStyle != None and len (Key) > 2:
2003 # Check Module style is EDK or EDKII.
2004 # Only append build option for the matched style module.
2005 if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:
2006 continue
2007 elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:
2008 continue
2009 Family = Key[0]
2010 Target, Tag, Arch, Tool, Attr = Key[1].split("_")
2011 # if tool chain family doesn't match, skip it
2012 if Tool not in self.ToolDefinition or Family =="":
2013 continue
2014 # option has been added before
2015 if Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_FAMILY]:
2016 continue
2017
2018 # expand any wildcard
2019 if Target == "*" or Target == self.BuildTarget:
2020 if Tag == "*" or Tag == self.ToolChain:
2021 if Arch == "*" or Arch == self.Arch:
2022 if Tool not in BuildOptions:
2023 BuildOptions[Tool] = {}
2024 if Attr != "FLAGS" or Attr not in BuildOptions[Tool]:
2025 BuildOptions[Tool][Attr] = Options[Key]
2026 else:
2027 # append options for the same tool
2028 BuildOptions[Tool][Attr] += " " + Options[Key]
2029 return BuildOptions
2030
2031 ## Append build options in platform to a module
2032 #
2033 # @param Module The module to which the build options will be appened
2034 #
2035 # @retval options The options appended with build options in platform
2036 #
2037 def ApplyBuildOption(self, Module):
2038 # Get the different options for the different style module
2039 if Module.AutoGenVersion < 0x00010005:
2040 PlatformOptions = self.EdkBuildOption
2041 else:
2042 PlatformOptions = self.EdkIIBuildOption
2043 ModuleOptions = self._ExpandBuildOption(Module.BuildOptions)
2044 if Module in self.Platform.Modules:
2045 PlatformModule = self.Platform.Modules[str(Module)]
2046 PlatformModuleOptions = self._ExpandBuildOption(PlatformModule.BuildOptions)
2047 else:
2048 PlatformModuleOptions = {}
2049
2050 AllTools = set(ModuleOptions.keys() + PlatformOptions.keys() + PlatformModuleOptions.keys() + self.ToolDefinition.keys())
2051 BuildOptions = {}
2052 for Tool in AllTools:
2053 if Tool not in BuildOptions:
2054 BuildOptions[Tool] = {}
2055
2056 for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, PlatformModuleOptions]:
2057 if Tool not in Options:
2058 continue
2059 for Attr in Options[Tool]:
2060 Value = Options[Tool][Attr]
2061 if Attr not in BuildOptions[Tool]:
2062 BuildOptions[Tool][Attr] = ""
2063 # check if override is indicated
2064 if Value.startswith('='):
2065 BuildOptions[Tool][Attr] = Value[1:]
2066 else:
2067 BuildOptions[Tool][Attr] += " " + Value
2068 if Module.AutoGenVersion < 0x00010005 and self.Workspace.UniFlag != None:
2069 #
2070 # Override UNI flag only for EDK module.
2071 #
2072 if 'BUILD' not in BuildOptions:
2073 BuildOptions['BUILD'] = {}
2074 BuildOptions['BUILD']['FLAGS'] = self.Workspace.UniFlag
2075 return BuildOptions
2076
2077 Platform = property(_GetPlatform)
2078 Name = property(_GetName)
2079 Guid = property(_GetGuid)
2080 Version = property(_GetVersion)
2081
2082 OutputDir = property(_GetOutputDir)
2083 BuildDir = property(_GetBuildDir)
2084 MakeFileDir = property(_GetMakeFileDir)
2085 FdfFile = property(_GetFdfFile)
2086
2087 PcdTokenNumber = property(_GetPcdTokenNumbers) # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
2088 DynamicPcdList = property(_GetDynamicPcdList) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
2089 NonDynamicPcdList = property(_GetNonDynamicPcdList) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
2090 NonDynamicPcdDict = property(_GetNonDynamicPcdDict)
2091 PackageList = property(_GetPackageList)
2092
2093 ToolDefinition = property(_GetToolDefinition) # toolcode : tool path
2094 ToolDefinitionFile = property(_GetToolDefFile) # toolcode : lib path
2095 ToolChainFamily = property(_GetToolChainFamily)
2096 BuildRuleFamily = property(_GetBuildRuleFamily)
2097 BuildOption = property(_GetBuildOptions) # toolcode : option
2098 EdkBuildOption = property(_GetEdkBuildOptions) # edktoolcode : option
2099 EdkIIBuildOption = property(_GetEdkIIBuildOptions) # edkiitoolcode : option
2100
2101 BuildCommand = property(_GetBuildCommand)
2102 BuildRule = property(_GetBuildRule)
2103 ModuleAutoGenList = property(_GetModuleAutoGenList)
2104 LibraryAutoGenList = property(_GetLibraryAutoGenList)
2105 GenFdsCommand = property(_GenFdsCommand)
2106
2107 ## ModuleAutoGen class
2108 #
2109 # This class encapsules the AutoGen behaviors for the build tools. In addition to
2110 # the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according
2111 # to the [depex] section in module's inf file.
2112 #
2113 class ModuleAutoGen(AutoGen):
2114 ## The real constructor of ModuleAutoGen
2115 #
2116 # This method is not supposed to be called by users of ModuleAutoGen. It's
2117 # only used by factory method __new__() to do real initialization work for an
2118 # object of ModuleAutoGen
2119 #
2120 # @param Workspace EdkIIWorkspaceBuild object
2121 # @param ModuleFile The path of module file
2122 # @param Target Build target (DEBUG, RELEASE)
2123 # @param Toolchain Name of tool chain
2124 # @param Arch The arch the module supports
2125 # @param PlatformFile Platform meta-file
2126 #
2127 def _Init(self, Workspace, ModuleFile, Target, Toolchain, Arch, PlatformFile):
2128 EdkLogger.debug(EdkLogger.DEBUG_9, "AutoGen module [%s] [%s]" % (ModuleFile, Arch))
2129 GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (ModuleFile, Arch, Toolchain, Target)
2130
2131 self.Workspace = Workspace
2132 self.WorkspaceDir = Workspace.WorkspaceDir
2133
2134 self.MetaFile = ModuleFile
2135 self.PlatformInfo = PlatformAutoGen(Workspace, PlatformFile, Target, Toolchain, Arch)
2136 # check if this module is employed by active platform
2137 if not self.PlatformInfo.ValidModule(self.MetaFile):
2138 EdkLogger.verbose("Module [%s] for [%s] is not employed by active platform\n" \
2139 % (self.MetaFile, Arch))
2140 return False
2141
2142 self.SourceDir = self.MetaFile.SubDir
2143 self.SourceOverrideDir = None
2144 # use overrided path defined in DSC file
2145 if self.MetaFile.Key in GlobalData.gOverrideDir:
2146 self.SourceOverrideDir = GlobalData.gOverrideDir[self.MetaFile.Key]
2147
2148 self.ToolChain = Toolchain
2149 self.BuildTarget = Target
2150 self.Arch = Arch
2151 self.ToolChainFamily = self.PlatformInfo.ToolChainFamily
2152 self.BuildRuleFamily = self.PlatformInfo.BuildRuleFamily
2153
2154 self.IsMakeFileCreated = False
2155 self.IsCodeFileCreated = False
2156 self.IsAsBuiltInfCreated = False
2157 self.DepexGenerated = False
2158
2159 self.BuildDatabase = self.Workspace.BuildDatabase
2160
2161 self._Module = None
2162 self._Name = None
2163 self._Guid = None
2164 self._Version = None
2165 self._ModuleType = None
2166 self._ComponentType = None
2167 self._PcdIsDriver = None
2168 self._AutoGenVersion = None
2169 self._LibraryFlag = None
2170 self._CustomMakefile = None
2171 self._Macro = None
2172
2173 self._BuildDir = None
2174 self._OutputDir = None
2175 self._DebugDir = None
2176 self._MakeFileDir = None
2177
2178 self._IncludePathList = None
2179 self._AutoGenFileList = None
2180 self._UnicodeFileList = None
2181 self._SourceFileList = None
2182 self._ObjectFileList = None
2183 self._BinaryFileList = None
2184
2185 self._DependentPackageList = None
2186 self._DependentLibraryList = None
2187 self._LibraryAutoGenList = None
2188 self._DerivedPackageList = None
2189 self._ModulePcdList = None
2190 self._LibraryPcdList = None
2191 self._PcdComments = sdict()
2192 self._GuidList = None
2193 self._GuidsUsedByPcd = None
2194 self._GuidComments = sdict()
2195 self._ProtocolList = None
2196 self._ProtocolComments = sdict()
2197 self._PpiList = None
2198 self._PpiComments = sdict()
2199 self._DepexList = None
2200 self._DepexExpressionList = None
2201 self._BuildOption = None
2202 self._BuildOptionIncPathList = None
2203 self._BuildTargets = None
2204 self._IntroBuildTargetList = None
2205 self._FinalBuildTargetList = None
2206 self._FileTypes = None
2207 self._BuildRules = None
2208
2209 ## The Modules referenced to this Library
2210 # Only Library has this attribute
2211 self._ReferenceModules = []
2212
2213 ## Store the FixedAtBuild Pcds
2214 #
2215 self._FixedAtBuildPcds = []
2216 self.ConstPcd = {}
2217 return True
2218
2219 def __repr__(self):
2220 return "%s [%s]" % (self.MetaFile, self.Arch)
2221
2222 # Get FixedAtBuild Pcds of this Module
2223 def _GetFixedAtBuildPcds(self):
2224 if self._FixedAtBuildPcds:
2225 return self._FixedAtBuildPcds
2226 for Pcd in self.ModulePcdList:
2227 if self.IsLibrary:
2228 if not (Pcd.Pending == False and Pcd.Type == "FixedAtBuild"):
2229 continue
2230 elif Pcd.Type != "FixedAtBuild":
2231 continue
2232 if Pcd not in self._FixedAtBuildPcds:
2233 self._FixedAtBuildPcds.append(Pcd)
2234
2235 return self._FixedAtBuildPcds
2236
2237 # Macros could be used in build_rule.txt (also Makefile)
2238 def _GetMacros(self):
2239 if self._Macro == None:
2240 self._Macro = sdict()
2241 self._Macro["WORKSPACE" ] = self.WorkspaceDir
2242 self._Macro["MODULE_NAME" ] = self.Name
2243 self._Macro["MODULE_GUID" ] = self.Guid
2244 self._Macro["MODULE_VERSION" ] = self.Version
2245 self._Macro["MODULE_TYPE" ] = self.ModuleType
2246 self._Macro["MODULE_FILE" ] = str(self.MetaFile)
2247 self._Macro["MODULE_FILE_BASE_NAME" ] = self.MetaFile.BaseName
2248 self._Macro["MODULE_RELATIVE_DIR" ] = self.SourceDir
2249 self._Macro["MODULE_DIR" ] = self.SourceDir
2250
2251 self._Macro["BASE_NAME" ] = self.Name
2252
2253 self._Macro["ARCH" ] = self.Arch
2254 self._Macro["TOOLCHAIN" ] = self.ToolChain
2255 self._Macro["TOOLCHAIN_TAG" ] = self.ToolChain
2256 self._Macro["TOOL_CHAIN_TAG" ] = self.ToolChain
2257 self._Macro["TARGET" ] = self.BuildTarget
2258
2259 self._Macro["BUILD_DIR" ] = self.PlatformInfo.BuildDir
2260 self._Macro["BIN_DIR" ] = os.path.join(self.PlatformInfo.BuildDir, self.Arch)
2261 self._Macro["LIB_DIR" ] = os.path.join(self.PlatformInfo.BuildDir, self.Arch)
2262 self._Macro["MODULE_BUILD_DIR" ] = self.BuildDir
2263 self._Macro["OUTPUT_DIR" ] = self.OutputDir
2264 self._Macro["DEBUG_DIR" ] = self.DebugDir
2265 return self._Macro
2266
2267 ## Return the module build data object
2268 def _GetModule(self):
2269 if self._Module == None:
2270 self._Module = self.Workspace.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]
2271 return self._Module
2272
2273 ## Return the module name
2274 def _GetBaseName(self):
2275 return self.Module.BaseName
2276
2277 ## Return the module DxsFile if exist
2278 def _GetDxsFile(self):
2279 return self.Module.DxsFile
2280
2281 ## Return the module SourceOverridePath
2282 def _GetSourceOverridePath(self):
2283 return self.Module.SourceOverridePath
2284
2285 ## Return the module meta-file GUID
2286 def _GetGuid(self):
2287 return self.Module.Guid
2288
2289 ## Return the module version
2290 def _GetVersion(self):
2291 return self.Module.Version
2292
2293 ## Return the module type
2294 def _GetModuleType(self):
2295 return self.Module.ModuleType
2296
2297 ## Return the component type (for Edk.x style of module)
2298 def _GetComponentType(self):
2299 return self.Module.ComponentType
2300
2301 ## Return the build type
2302 def _GetBuildType(self):
2303 return self.Module.BuildType
2304
2305 ## Return the PCD_IS_DRIVER setting
2306 def _GetPcdIsDriver(self):
2307 return self.Module.PcdIsDriver
2308
2309 ## Return the autogen version, i.e. module meta-file version
2310 def _GetAutoGenVersion(self):
2311 return self.Module.AutoGenVersion
2312
2313 ## Check if the module is library or not
2314 def _IsLibrary(self):
2315 if self._LibraryFlag == None:
2316 if self.Module.LibraryClass != None and self.Module.LibraryClass != []:
2317 self._LibraryFlag = True
2318 else:
2319 self._LibraryFlag = False
2320 return self._LibraryFlag
2321
2322 ## Check if the module is binary module or not
2323 def _IsBinaryModule(self):
2324 return self.Module.IsBinaryModule
2325
2326 ## Return the directory to store intermediate files of the module
2327 def _GetBuildDir(self):
2328 if self._BuildDir == None:
2329 self._BuildDir = path.join(
2330 self.PlatformInfo.BuildDir,
2331 self.Arch,
2332 self.SourceDir,
2333 self.MetaFile.BaseName
2334 )
2335 CreateDirectory(self._BuildDir)
2336 return self._BuildDir
2337
2338 ## Return the directory to store the intermediate object files of the mdoule
2339 def _GetOutputDir(self):
2340 if self._OutputDir == None:
2341 self._OutputDir = path.join(self.BuildDir, "OUTPUT")
2342 CreateDirectory(self._OutputDir)
2343 return self._OutputDir
2344
2345 ## Return the directory to store auto-gened source files of the mdoule
2346 def _GetDebugDir(self):
2347 if self._DebugDir == None:
2348 self._DebugDir = path.join(self.BuildDir, "DEBUG")
2349 CreateDirectory(self._DebugDir)
2350 return self._DebugDir
2351
2352 ## Return the path of custom file
2353 def _GetCustomMakefile(self):
2354 if self._CustomMakefile == None:
2355 self._CustomMakefile = {}
2356 for Type in self.Module.CustomMakefile:
2357 if Type in gMakeTypeMap:
2358 MakeType = gMakeTypeMap[Type]
2359 else:
2360 MakeType = 'nmake'
2361 if self.SourceOverrideDir != None:
2362 File = os.path.join(self.SourceOverrideDir, self.Module.CustomMakefile[Type])
2363 if not os.path.exists(File):
2364 File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])
2365 else:
2366 File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])
2367 self._CustomMakefile[MakeType] = File
2368 return self._CustomMakefile
2369
2370 ## Return the directory of the makefile
2371 #
2372 # @retval string The directory string of module's makefile
2373 #
2374 def _GetMakeFileDir(self):
2375 return self.BuildDir
2376
2377 ## Return build command string
2378 #
2379 # @retval string Build command string
2380 #
2381 def _GetBuildCommand(self):
2382 return self.PlatformInfo.BuildCommand
2383
2384 ## Get object list of all packages the module and its dependent libraries belong to
2385 #
2386 # @retval list The list of package object
2387 #
2388 def _GetDerivedPackageList(self):
2389 PackageList = []
2390 for M in [self.Module] + self.DependentLibraryList:
2391 for Package in M.Packages:
2392 if Package in PackageList:
2393 continue
2394 PackageList.append(Package)
2395 return PackageList
2396
2397 ## Merge dependency expression
2398 #
2399 # @retval list The token list of the dependency expression after parsed
2400 #
2401 def _GetDepexTokenList(self):
2402 if self._DepexList == None:
2403 self._DepexList = {}
2404 if self.DxsFile or self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:
2405 return self._DepexList
2406
2407 self._DepexList[self.ModuleType] = []
2408
2409 for ModuleType in self._DepexList:
2410 DepexList = self._DepexList[ModuleType]
2411 #
2412 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
2413 #
2414 for M in [self.Module] + self.DependentLibraryList:
2415 Inherited = False
2416 for D in M.Depex[self.Arch, ModuleType]:
2417 if DepexList != []:
2418 DepexList.append('AND')
2419 DepexList.append('(')
2420 DepexList.extend(D)
2421 if DepexList[-1] == 'END': # no need of a END at this time
2422 DepexList.pop()
2423 DepexList.append(')')
2424 Inherited = True
2425 if Inherited:
2426 EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexList))
2427 if 'BEFORE' in DepexList or 'AFTER' in DepexList:
2428 break
2429 if len(DepexList) > 0:
2430 EdkLogger.verbose('')
2431 return self._DepexList
2432
2433 ## Merge dependency expression
2434 #
2435 # @retval list The token list of the dependency expression after parsed
2436 #
2437 def _GetDepexExpressionTokenList(self):
2438 if self._DepexExpressionList == None:
2439 self._DepexExpressionList = {}
2440 if self.DxsFile or self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:
2441 return self._DepexExpressionList
2442
2443 self._DepexExpressionList[self.ModuleType] = ''
2444
2445 for ModuleType in self._DepexExpressionList:
2446 DepexExpressionList = self._DepexExpressionList[ModuleType]
2447 #
2448 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
2449 #
2450 for M in [self.Module] + self.DependentLibraryList:
2451 Inherited = False
2452 for D in M.DepexExpression[self.Arch, ModuleType]:
2453 if DepexExpressionList != '':
2454 DepexExpressionList += ' AND '
2455 DepexExpressionList += '('
2456 DepexExpressionList += D
2457 DepexExpressionList = DepexExpressionList.rstrip('END').strip()
2458 DepexExpressionList += ')'
2459 Inherited = True
2460 if Inherited:
2461 EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexExpressionList))
2462 if 'BEFORE' in DepexExpressionList or 'AFTER' in DepexExpressionList:
2463 break
2464 if len(DepexExpressionList) > 0:
2465 EdkLogger.verbose('')
2466 self._DepexExpressionList[ModuleType] = DepexExpressionList
2467 return self._DepexExpressionList
2468
2469 ## Return the list of specification version required for the module
2470 #
2471 # @retval list The list of specification defined in module file
2472 #
2473 def _GetSpecification(self):
2474 return self.Module.Specification
2475
2476 ## Tool option for the module build
2477 #
2478 # @param PlatformInfo The object of PlatformBuildInfo
2479 # @retval dict The dict containing valid options
2480 #
2481 def _GetModuleBuildOption(self):
2482 if self._BuildOption == None:
2483 self._BuildOption = self.PlatformInfo.ApplyBuildOption(self.Module)
2484 return self._BuildOption
2485
2486 ## Get include path list from tool option for the module build
2487 #
2488 # @retval list The include path list
2489 #
2490 def _GetBuildOptionIncPathList(self):
2491 if self._BuildOptionIncPathList == None:
2492 #
2493 # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
2494 # is the former use /I , the Latter used -I to specify include directories
2495 #
2496 if self.PlatformInfo.ToolChainFamily in ('MSFT'):
2497 gBuildOptIncludePattern = re.compile(r"(?:.*?)/I[ \t]*([^ ]*)", re.MULTILINE|re.DOTALL)
2498 elif self.PlatformInfo.ToolChainFamily in ('INTEL', 'GCC', 'RVCT'):
2499 gBuildOptIncludePattern = re.compile(r"(?:.*?)-I[ \t]*([^ ]*)", re.MULTILINE|re.DOTALL)
2500 else:
2501 #
2502 # New ToolChainFamily, don't known whether there is option to specify include directories
2503 #
2504 self._BuildOptionIncPathList = []
2505 return self._BuildOptionIncPathList
2506
2507 BuildOptionIncPathList = []
2508 for Tool in ('CC', 'PP', 'VFRPP', 'ASLPP', 'ASLCC', 'APP', 'ASM'):
2509 Attr = 'FLAGS'
2510 try:
2511 FlagOption = self.BuildOption[Tool][Attr]
2512 except KeyError:
2513 FlagOption = ''
2514
2515 if self.PlatformInfo.ToolChainFamily != 'RVCT':
2516 IncPathList = [NormPath(Path, self.Macros) for Path in gBuildOptIncludePattern.findall(FlagOption)]
2517 else:
2518 #
2519 # RVCT may specify a list of directory seperated by commas
2520 #
2521 IncPathList = []
2522 for Path in gBuildOptIncludePattern.findall(FlagOption):
2523 PathList = GetSplitList(Path, TAB_COMMA_SPLIT)
2524 IncPathList += [NormPath(PathEntry, self.Macros) for PathEntry in PathList]
2525
2526 #
2527 # EDK II modules must not reference header files outside of the packages they depend on or
2528 # within the module's directory tree. Report error if violation.
2529 #
2530 if self.AutoGenVersion >= 0x00010005 and len(IncPathList) > 0:
2531 for Path in IncPathList:
2532 if (Path not in self.IncludePathList) and (CommonPath([Path, self.MetaFile.Dir]) != self.MetaFile.Dir):
2533 ErrMsg = "The include directory for the EDK II module in this line is invalid %s specified in %s FLAGS '%s'" % (Path, Tool, FlagOption)
2534 EdkLogger.error("build",
2535 PARAMETER_INVALID,
2536 ExtraData = ErrMsg,
2537 File = str(self.MetaFile))
2538
2539
2540 BuildOptionIncPathList += IncPathList
2541
2542 self._BuildOptionIncPathList = BuildOptionIncPathList
2543
2544 return self._BuildOptionIncPathList
2545
2546 ## Return a list of files which can be built from source
2547 #
2548 # What kind of files can be built is determined by build rules in
2549 # $(WORKSPACE)/Conf/build_rule.txt and toolchain family.
2550 #
2551 def _GetSourceFileList(self):
2552 if self._SourceFileList == None:
2553 self._SourceFileList = []
2554 for F in self.Module.Sources:
2555 # match tool chain
2556 if F.TagName not in ("", "*", self.ToolChain):
2557 EdkLogger.debug(EdkLogger.DEBUG_9, "The toolchain [%s] for processing file [%s] is found, "
2558 "but [%s] is needed" % (F.TagName, str(F), self.ToolChain))
2559 continue
2560 # match tool chain family
2561 if F.ToolChainFamily not in ("", "*", self.ToolChainFamily):
2562 EdkLogger.debug(
2563 EdkLogger.DEBUG_0,
2564 "The file [%s] must be built by tools of [%s], " \
2565 "but current toolchain family is [%s]" \
2566 % (str(F), F.ToolChainFamily, self.ToolChainFamily))
2567 continue
2568
2569 # add the file path into search path list for file including
2570 if F.Dir not in self.IncludePathList and self.AutoGenVersion >= 0x00010005:
2571 self.IncludePathList.insert(0, F.Dir)
2572 self._SourceFileList.append(F)
2573 self._ApplyBuildRule(F, TAB_UNKNOWN_FILE)
2574 return self._SourceFileList
2575
2576 ## Return the list of unicode files
2577 def _GetUnicodeFileList(self):
2578 if self._UnicodeFileList == None:
2579 if TAB_UNICODE_FILE in self.FileTypes:
2580 self._UnicodeFileList = self.FileTypes[TAB_UNICODE_FILE]
2581 else:
2582 self._UnicodeFileList = []
2583 return self._UnicodeFileList
2584
2585 ## Return a list of files which can be built from binary
2586 #
2587 # "Build" binary files are just to copy them to build directory.
2588 #
2589 # @retval list The list of files which can be built later
2590 #
2591 def _GetBinaryFiles(self):
2592 if self._BinaryFileList == None:
2593 self._BinaryFileList = []
2594 for F in self.Module.Binaries:
2595 if F.Target not in ['COMMON', '*'] and F.Target != self.BuildTarget:
2596 continue
2597 self._BinaryFileList.append(F)
2598 self._ApplyBuildRule(F, F.Type)
2599 return self._BinaryFileList
2600
2601 def _GetBuildRules(self):
2602 if self._BuildRules == None:
2603 BuildRules = {}
2604 BuildRuleDatabase = self.PlatformInfo.BuildRule
2605 for Type in BuildRuleDatabase.FileTypeList:
2606 #first try getting build rule by BuildRuleFamily
2607 RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.BuildRuleFamily]
2608 if not RuleObject:
2609 # build type is always module type, but ...
2610 if self.ModuleType != self.BuildType:
2611 RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.BuildRuleFamily]
2612 #second try getting build rule by ToolChainFamily
2613 if not RuleObject:
2614 RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.ToolChainFamily]
2615 if not RuleObject:
2616 # build type is always module type, but ...
2617 if self.ModuleType != self.BuildType:
2618 RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.ToolChainFamily]
2619 if not RuleObject:
2620 continue
2621 RuleObject = RuleObject.Instantiate(self.Macros)
2622 BuildRules[Type] = RuleObject
2623 for Ext in RuleObject.SourceFileExtList:
2624 BuildRules[Ext] = RuleObject
2625 self._BuildRules = BuildRules
2626 return self._BuildRules
2627
2628 def _ApplyBuildRule(self, File, FileType):
2629 if self._BuildTargets == None:
2630 self._IntroBuildTargetList = set()
2631 self._FinalBuildTargetList = set()
2632 self._BuildTargets = {}
2633 self._FileTypes = {}
2634
2635 SubDirectory = os.path.join(self.OutputDir, File.SubDir)
2636 if not os.path.exists(SubDirectory):
2637 CreateDirectory(SubDirectory)
2638 LastTarget = None
2639 RuleChain = []
2640 SourceList = [File]
2641 Index = 0
2642 while Index < len(SourceList):
2643 Source = SourceList[Index]
2644 Index = Index + 1
2645
2646 if Source != File:
2647 CreateDirectory(Source.Dir)
2648
2649 if File.IsBinary and File == Source and self._BinaryFileList != None and File in self._BinaryFileList:
2650 # Skip all files that are not binary libraries
2651 if not self.IsLibrary:
2652 continue
2653 RuleObject = self.BuildRules[TAB_DEFAULT_BINARY_FILE]
2654 elif FileType in self.BuildRules:
2655 RuleObject = self.BuildRules[FileType]
2656 elif Source.Ext in self.BuildRules:
2657 RuleObject = self.BuildRules[Source.Ext]
2658 else:
2659 # stop at no more rules
2660 if LastTarget:
2661 self._FinalBuildTargetList.add(LastTarget)
2662 break
2663
2664 FileType = RuleObject.SourceFileType
2665 if FileType not in self._FileTypes:
2666 self._FileTypes[FileType] = set()
2667 self._FileTypes[FileType].add(Source)
2668
2669 # stop at STATIC_LIBRARY for library
2670 if self.IsLibrary and FileType == TAB_STATIC_LIBRARY:
2671 if LastTarget:
2672 self._FinalBuildTargetList.add(LastTarget)
2673 break
2674
2675 Target = RuleObject.Apply(Source)
2676 if not Target:
2677 if LastTarget:
2678 self._FinalBuildTargetList.add(LastTarget)
2679 break
2680 elif not Target.Outputs:
2681 # Only do build for target with outputs
2682 self._FinalBuildTargetList.add(Target)
2683
2684 if FileType not in self._BuildTargets:
2685 self._BuildTargets[FileType] = set()
2686 self._BuildTargets[FileType].add(Target)
2687
2688 if not Source.IsBinary and Source == File:
2689 self._IntroBuildTargetList.add(Target)
2690
2691 # to avoid cyclic rule
2692 if FileType in RuleChain:
2693 break
2694
2695 RuleChain.append(FileType)
2696 SourceList.extend(Target.Outputs)
2697 LastTarget = Target
2698 FileType = TAB_UNKNOWN_FILE
2699
2700 def _GetTargets(self):
2701 if self._BuildTargets == None:
2702 self._IntroBuildTargetList = set()
2703 self._FinalBuildTargetList = set()
2704 self._BuildTargets = {}
2705 self._FileTypes = {}
2706
2707 #TRICK: call _GetSourceFileList to apply build rule for source files
2708 if self.SourceFileList:
2709 pass
2710
2711 #TRICK: call _GetBinaryFileList to apply build rule for binary files
2712 if self.BinaryFileList:
2713 pass
2714
2715 return self._BuildTargets
2716
2717 def _GetIntroTargetList(self):
2718 self._GetTargets()
2719 return self._IntroBuildTargetList
2720
2721 def _GetFinalTargetList(self):
2722 self._GetTargets()
2723 return self._FinalBuildTargetList
2724
2725 def _GetFileTypes(self):
2726 self._GetTargets()
2727 return self._FileTypes
2728
2729 ## Get the list of package object the module depends on
2730 #
2731 # @retval list The package object list
2732 #
2733 def _GetDependentPackageList(self):
2734 return self.Module.Packages
2735
2736 ## Return the list of auto-generated code file
2737 #
2738 # @retval list The list of auto-generated file
2739 #
2740 def _GetAutoGenFileList(self):
2741 UniStringAutoGenC = True
2742 UniStringBinBuffer = StringIO()
2743 if self.BuildType == 'UEFI_HII':
2744 UniStringAutoGenC = False
2745 if self._AutoGenFileList == None:
2746 self._AutoGenFileList = {}
2747 AutoGenC = TemplateString()
2748 AutoGenH = TemplateString()
2749 StringH = TemplateString()
2750 GenC.CreateCode(self, AutoGenC, AutoGenH, StringH, UniStringAutoGenC, UniStringBinBuffer)
2751 #
2752 # AutoGen.c is generated if there are library classes in inf, or there are object files
2753 #
2754 if str(AutoGenC) != "" and (len(self.Module.LibraryClasses) > 0
2755 or TAB_OBJECT_FILE in self.FileTypes):
2756 AutoFile = PathClass(gAutoGenCodeFileName, self.DebugDir)
2757 self._AutoGenFileList[AutoFile] = str(AutoGenC)
2758 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
2759 if str(AutoGenH) != "":
2760 AutoFile = PathClass(gAutoGenHeaderFileName, self.DebugDir)
2761 self._AutoGenFileList[AutoFile] = str(AutoGenH)
2762 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
2763 if str(StringH) != "":
2764 AutoFile = PathClass(gAutoGenStringFileName % {"module_name":self.Name}, self.DebugDir)
2765 self._AutoGenFileList[AutoFile] = str(StringH)
2766 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
2767 if UniStringBinBuffer != None and UniStringBinBuffer.getvalue() != "":
2768 AutoFile = PathClass(gAutoGenStringFormFileName % {"module_name":self.Name}, self.OutputDir)
2769 self._AutoGenFileList[AutoFile] = UniStringBinBuffer.getvalue()
2770 AutoFile.IsBinary = True
2771 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
2772 if UniStringBinBuffer != None:
2773 UniStringBinBuffer.close()
2774 return self._AutoGenFileList
2775
2776 ## Return the list of library modules explicitly or implicityly used by this module
2777 def _GetLibraryList(self):
2778 if self._DependentLibraryList == None:
2779 # only merge library classes and PCD for non-library module
2780 if self.IsLibrary:
2781 self._DependentLibraryList = []
2782 else:
2783 if self.AutoGenVersion < 0x00010005:
2784 self._DependentLibraryList = self.PlatformInfo.ResolveLibraryReference(self.Module)
2785 else:
2786 self._DependentLibraryList = self.PlatformInfo.ApplyLibraryInstance(self.Module)
2787 return self._DependentLibraryList
2788
2789 @staticmethod
2790 def UpdateComments(Recver, Src):
2791 for Key in Src:
2792 if Key not in Recver:
2793 Recver[Key] = []
2794 Recver[Key].extend(Src[Key])
2795 ## Get the list of PCDs from current module
2796 #
2797 # @retval list The list of PCD
2798 #
2799 def _GetModulePcdList(self):
2800 if self._ModulePcdList == None:
2801 # apply PCD settings from platform
2802 self._ModulePcdList = self.PlatformInfo.ApplyPcdSetting(self.Module, self.Module.Pcds)
2803 self.UpdateComments(self._PcdComments, self.Module.PcdComments)
2804 return self._ModulePcdList
2805
2806 ## Get the list of PCDs from dependent libraries
2807 #
2808 # @retval list The list of PCD
2809 #
2810 def _GetLibraryPcdList(self):
2811 if self._LibraryPcdList == None:
2812 Pcds = sdict()
2813 if not self.IsLibrary:
2814 # get PCDs from dependent libraries
2815 for Library in self.DependentLibraryList:
2816 self.UpdateComments(self._PcdComments, Library.PcdComments)
2817 for Key in Library.Pcds:
2818 # skip duplicated PCDs
2819 if Key in self.Module.Pcds or Key in Pcds:
2820 continue
2821 Pcds[Key] = copy.copy(Library.Pcds[Key])
2822 # apply PCD settings from platform
2823 self._LibraryPcdList = self.PlatformInfo.ApplyPcdSetting(self.Module, Pcds)
2824 else:
2825 self._LibraryPcdList = []
2826 return self._LibraryPcdList
2827
2828 ## Get the GUID value mapping
2829 #
2830 # @retval dict The mapping between GUID cname and its value
2831 #
2832 def _GetGuidList(self):
2833 if self._GuidList == None:
2834 self._GuidList = self.Module.Guids
2835 for Library in self.DependentLibraryList:
2836 self._GuidList.update(Library.Guids)
2837 self.UpdateComments(self._GuidComments, Library.GuidComments)
2838 self.UpdateComments(self._GuidComments, self.Module.GuidComments)
2839 return self._GuidList
2840
2841 def GetGuidsUsedByPcd(self):
2842 if self._GuidsUsedByPcd == None:
2843 self._GuidsUsedByPcd = sdict()
2844 self._GuidsUsedByPcd.update(self.Module.GetGuidsUsedByPcd())
2845 for Library in self.DependentLibraryList:
2846 self._GuidsUsedByPcd.update(Library.GetGuidsUsedByPcd())
2847 return self._GuidsUsedByPcd
2848 ## Get the protocol value mapping
2849 #
2850 # @retval dict The mapping between protocol cname and its value
2851 #
2852 def _GetProtocolList(self):
2853 if self._ProtocolList == None:
2854 self._ProtocolList = self.Module.Protocols
2855 for Library in self.DependentLibraryList:
2856 self._ProtocolList.update(Library.Protocols)
2857 self.UpdateComments(self._ProtocolComments, Library.ProtocolComments)
2858 self.UpdateComments(self._ProtocolComments, self.Module.ProtocolComments)
2859 return self._ProtocolList
2860
2861 ## Get the PPI value mapping
2862 #
2863 # @retval dict The mapping between PPI cname and its value
2864 #
2865 def _GetPpiList(self):
2866 if self._PpiList == None:
2867 self._PpiList = self.Module.Ppis
2868 for Library in self.DependentLibraryList:
2869 self._PpiList.update(Library.Ppis)
2870 self.UpdateComments(self._PpiComments, Library.PpiComments)
2871 self.UpdateComments(self._PpiComments, self.Module.PpiComments)
2872 return self._PpiList
2873
2874 ## Get the list of include search path
2875 #
2876 # @retval list The list path
2877 #
2878 def _GetIncludePathList(self):
2879 if self._IncludePathList == None:
2880 self._IncludePathList = []
2881 if self.AutoGenVersion < 0x00010005:
2882 for Inc in self.Module.Includes:
2883 if Inc not in self._IncludePathList:
2884 self._IncludePathList.append(Inc)
2885 # for Edk modules
2886 Inc = path.join(Inc, self.Arch.capitalize())
2887 if os.path.exists(Inc) and Inc not in self._IncludePathList:
2888 self._IncludePathList.append(Inc)
2889 # Edk module needs to put DEBUG_DIR at the end of search path and not to use SOURCE_DIR all the time
2890 self._IncludePathList.append(self.DebugDir)
2891 else:
2892 self._IncludePathList.append(self.MetaFile.Dir)
2893 self._IncludePathList.append(self.DebugDir)
2894
2895 for Package in self.Module.Packages:
2896 PackageDir = path.join(self.WorkspaceDir, Package.MetaFile.Dir)
2897 if PackageDir not in self._IncludePathList:
2898 self._IncludePathList.append(PackageDir)
2899 for Inc in Package.Includes:
2900 if Inc not in self._IncludePathList:
2901 self._IncludePathList.append(str(Inc))
2902 return self._IncludePathList
2903
2904 ## Create AsBuilt INF file the module
2905 #
2906 def CreateAsBuiltInf(self):
2907 if self.IsAsBuiltInfCreated:
2908 return
2909
2910 # Skip the following code for EDK I inf
2911 if self.AutoGenVersion < 0x00010005:
2912 return
2913
2914 # Skip the following code for libraries
2915 if self.IsLibrary:
2916 return
2917
2918 # Skip the following code for modules with no source files
2919 if self.SourceFileList == None or self.SourceFileList == []:
2920 return
2921
2922 # Skip the following code for modules without any binary files
2923 if self.BinaryFileList <> None and self.BinaryFileList <> []:
2924 return
2925
2926 ### TODO: How to handles mixed source and binary modules
2927
2928 # Find all DynamicEx and PatchableInModule PCDs used by this module and dependent libraries
2929 # Also find all packages that the DynamicEx PCDs depend on
2930 Pcds = []
2931 PatchablePcds = {}
2932 Packages = []
2933 PcdCheckList = []
2934 PcdTokenSpaceList = []
2935 for Pcd in self.ModulePcdList + self.LibraryPcdList:
2936 if Pcd.Type == TAB_PCDS_PATCHABLE_IN_MODULE:
2937 PatchablePcds[Pcd.TokenCName] = Pcd
2938 PcdCheckList.append((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, 'PatchableInModule'))
2939 elif Pcd.Type in GenC.gDynamicExPcd:
2940 if Pcd not in Pcds:
2941 Pcds += [Pcd]
2942 PcdCheckList.append((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, 'DynamicEx'))
2943 PcdCheckList.append((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, 'Dynamic'))
2944 PcdTokenSpaceList.append(Pcd.TokenSpaceGuidCName)
2945 GuidList = sdict()
2946 GuidList.update(self.GuidList)
2947 for TokenSpace in self.GetGuidsUsedByPcd():
2948 # If token space is not referred by patch PCD or Ex PCD, remove the GUID from GUID list
2949 # The GUIDs in GUIDs section should really be the GUIDs in source INF or referred by Ex an patch PCDs
2950 if TokenSpace not in PcdTokenSpaceList and TokenSpace in GuidList:
2951 GuidList.pop(TokenSpace)
2952 CheckList = (GuidList, self.PpiList, self.ProtocolList, PcdCheckList)
2953 for Package in self.DerivedPackageList:
2954 if Package in Packages:
2955 continue
2956 BeChecked = (Package.Guids, Package.Ppis, Package.Protocols, Package.Pcds)
2957 Found = False
2958 for Index in range(len(BeChecked)):
2959 for Item in CheckList[Index]:
2960 if Item in BeChecked[Index]:
2961 Packages += [Package]
2962 Found = True
2963 break
2964 if Found: break
2965
2966 ModuleType = self.ModuleType
2967 if ModuleType == 'UEFI_DRIVER' and self.DepexGenerated:
2968 ModuleType = 'DXE_DRIVER'
2969
2970 DriverType = ''
2971 if self.PcdIsDriver != '':
2972 DriverType = self.PcdIsDriver
2973
2974 AsBuiltInfDict = {
2975 'module_name' : self.Name,
2976 'module_guid' : self.Guid,
2977 'module_module_type' : ModuleType,
2978 'module_version_string' : self.Version,
2979 'pcd_is_driver_string' : [],
2980 'module_uefi_specification_version' : [],
2981 'module_pi_specification_version' : [],
2982 'module_arch' : self.Arch,
2983 'package_item' : ['%s' % (Package.MetaFile.File.replace('\\','/')) for Package in Packages],
2984 'binary_item' : [],
2985 'patchablepcd_item' : [],
2986 'pcd_item' : [],
2987 'protocol_item' : [],
2988 'ppi_item' : [],
2989 'guid_item' : [],
2990 'flags_item' : [],
2991 'libraryclasses_item' : []
2992 }
2993 AsBuiltInfDict['module_inf_version'] = '0x%08x' % self.AutoGenVersion
2994 if DriverType:
2995 AsBuiltInfDict['pcd_is_driver_string'] += [DriverType]
2996
2997 if 'UEFI_SPECIFICATION_VERSION' in self.Specification:
2998 AsBuiltInfDict['module_uefi_specification_version'] += [self.Specification['UEFI_SPECIFICATION_VERSION']]
2999 if 'PI_SPECIFICATION_VERSION' in self.Specification:
3000 AsBuiltInfDict['module_pi_specification_version'] += [self.Specification['PI_SPECIFICATION_VERSION']]
3001
3002 OutputDir = self.OutputDir.replace('\\','/').strip('/')
3003 if self.ModuleType in ['BASE', 'USER_DEFINED']:
3004 for Item in self.CodaTargetList:
3005 File = Item.Target.Path.replace('\\','/').strip('/').replace(OutputDir,'').strip('/')
3006 if Item.Target.Ext.lower() == '.aml':
3007 AsBuiltInfDict['binary_item'] += ['ASL|' + File]
3008 elif Item.Target.Ext.lower() == '.acpi':
3009 AsBuiltInfDict['binary_item'] += ['ACPI|' + File]
3010 else:
3011 AsBuiltInfDict['binary_item'] += ['BIN|' + File]
3012 else:
3013 for Item in self.CodaTargetList:
3014 File = Item.Target.Path.replace('\\','/').strip('/').replace(OutputDir,'').strip('/')
3015 if Item.Target.Ext.lower() == '.efi':
3016 AsBuiltInfDict['binary_item'] += ['PE32|' + self.Name + '.efi']
3017 else:
3018 AsBuiltInfDict['binary_item'] += ['BIN|' + File]
3019 if self.DepexGenerated:
3020 if self.ModuleType in ['PEIM']:
3021 AsBuiltInfDict['binary_item'] += ['PEI_DEPEX|' + self.Name + '.depex']
3022 if self.ModuleType in ['DXE_DRIVER','DXE_RUNTIME_DRIVER','DXE_SAL_DRIVER','UEFI_DRIVER']:
3023 AsBuiltInfDict['binary_item'] += ['DXE_DEPEX|' + self.Name + '.depex']
3024 if self.ModuleType in ['DXE_SMM_DRIVER']:
3025 AsBuiltInfDict['binary_item'] += ['SMM_DEPEX|' + self.Name + '.depex']
3026
3027 for Root, Dirs, Files in os.walk(OutputDir):
3028 for File in Files:
3029 if File.lower().endswith('.pdb'):
3030 AsBuiltInfDict['binary_item'] += ['DISPOSABLE|' + File]
3031 HeaderComments = self.Module.HeaderComments
3032 StartPos = 0
3033 for Index in range(len(HeaderComments)):
3034 if HeaderComments[Index].find('@BinaryHeader') != -1:
3035 HeaderComments[Index] = HeaderComments[Index].replace('@BinaryHeader', '@file')
3036 StartPos = Index
3037 break
3038 AsBuiltInfDict['header_comments'] = '\n'.join(HeaderComments[StartPos:]).replace(':#', '://')
3039 GenList = [
3040 (self.ProtocolList, self._ProtocolComments, 'protocol_item'),
3041 (self.PpiList, self._PpiComments, 'ppi_item'),
3042 (GuidList, self._GuidComments, 'guid_item')
3043 ]
3044 for Item in GenList:
3045 for CName in Item[0]:
3046 Comments = ''
3047 if CName in Item[1]:
3048 Comments = '\n '.join(Item[1][CName])
3049 Entry = CName
3050 if Comments:
3051 Entry = Comments + '\n ' + CName
3052 AsBuiltInfDict[Item[2]].append(Entry)
3053 PatchList = parsePcdInfoFromMapFile(
3054 os.path.join(self.OutputDir, self.Name + '.map'),
3055 os.path.join(self.OutputDir, self.Name + '.efi')
3056 )
3057 if PatchList:
3058 for PatchPcd in PatchList:
3059 if PatchPcd[0] not in PatchablePcds:
3060 continue
3061 Pcd = PatchablePcds[PatchPcd[0]]
3062 PcdValue = ''
3063 if Pcd.DatumType != 'VOID*':
3064 HexFormat = '0x%02x'
3065 if Pcd.DatumType == 'UINT16':
3066 HexFormat = '0x%04x'
3067 elif Pcd.DatumType == 'UINT32':
3068 HexFormat = '0x%08x'
3069 elif Pcd.DatumType == 'UINT64':
3070 HexFormat = '0x%016x'
3071 PcdValue = HexFormat % int(Pcd.DefaultValue, 0)
3072 else:
3073 if Pcd.MaxDatumSize == None or Pcd.MaxDatumSize == '':
3074 EdkLogger.error("build", AUTOGEN_ERROR,
3075 "Unknown [MaxDatumSize] of PCD [%s.%s]" % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
3076 )
3077 ArraySize = int(Pcd.MaxDatumSize, 0)
3078 PcdValue = Pcd.DefaultValue
3079 if PcdValue[0] != '{':
3080 Unicode = False
3081 if PcdValue[0] == 'L':
3082 Unicode = True
3083 PcdValue = PcdValue.lstrip('L')
3084 PcdValue = eval(PcdValue)
3085 NewValue = '{'
3086 for Index in range(0, len(PcdValue)):
3087 if Unicode:
3088 CharVal = ord(PcdValue[Index])
3089 NewValue = NewValue + '0x%02x' % (CharVal & 0x00FF) + ', ' \
3090 + '0x%02x' % (CharVal >> 8) + ', '
3091 else:
3092 NewValue = NewValue + '0x%02x' % (ord(PcdValue[Index]) % 0x100) + ', '
3093 Padding = '0x00, '
3094 if Unicode:
3095 Padding = Padding * 2
3096 ArraySize = ArraySize / 2
3097 if ArraySize < (len(PcdValue) + 1):
3098 EdkLogger.error("build", AUTOGEN_ERROR,
3099 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
3100 )
3101 if ArraySize > len(PcdValue) + 1:
3102 NewValue = NewValue + Padding * (ArraySize - len(PcdValue) - 1)
3103 PcdValue = NewValue + Padding.strip().rstrip(',') + '}'
3104 elif len(PcdValue.split(',')) <= ArraySize:
3105 PcdValue = PcdValue.rstrip('}') + ', 0x00' * (ArraySize - len(PcdValue.split(',')))
3106 PcdValue += '}'
3107 else:
3108 EdkLogger.error("build", AUTOGEN_ERROR,
3109 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
3110 )
3111 PcdItem = '%s.%s|%s|0x%X' % \
3112 (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, PcdValue, PatchPcd[1])
3113 PcdComments = ''
3114 if (Pcd.TokenSpaceGuidCName, Pcd.TokenCName) in self._PcdComments:
3115 PcdComments = '\n '.join(self._PcdComments[Pcd.TokenSpaceGuidCName, Pcd.TokenCName])
3116 if PcdComments:
3117 PcdItem = PcdComments + '\n ' + PcdItem
3118 AsBuiltInfDict['patchablepcd_item'].append(PcdItem)
3119 for Pcd in Pcds:
3120 PcdComments = ''
3121 PcdCommentList = []
3122 HiiInfo = ''
3123 if Pcd.Type == TAB_PCDS_DYNAMIC_EX_HII:
3124 for SkuName in Pcd.SkuInfoList:
3125 SkuInfo = Pcd.SkuInfoList[SkuName]
3126 HiiInfo = '## %s|%s|%s' % (SkuInfo.VariableName, SkuInfo.VariableGuid, SkuInfo.VariableOffset)
3127 break
3128 if (Pcd.TokenSpaceGuidCName, Pcd.TokenCName) in self._PcdComments:
3129 PcdCommentList = self._PcdComments[Pcd.TokenSpaceGuidCName, Pcd.TokenCName][:]
3130 if HiiInfo:
3131 UsageIndex = -1
3132 for Index, Comment in enumerate(PcdCommentList):
3133 for Usage in UsageList:
3134 if Comment.find(Usage) != -1:
3135 UsageIndex = Index
3136 break
3137 if UsageIndex != -1:
3138 PcdCommentList[UsageIndex] = PcdCommentList[UsageIndex] + ' ' + HiiInfo
3139 else:
3140 PcdCommentList.append('## ' + HiiInfo)
3141 PcdComments = '\n '.join(PcdCommentList)
3142 PcdEntry = Pcd.TokenSpaceGuidCName + '.' + Pcd.TokenCName
3143 if PcdComments:
3144 PcdEntry = PcdComments + '\n ' + PcdEntry
3145 AsBuiltInfDict['pcd_item'] += [PcdEntry]
3146 for Item in self.BuildOption:
3147 if 'FLAGS' in self.BuildOption[Item]:
3148 AsBuiltInfDict['flags_item'] += ['%s:%s_%s_%s_%s_FLAGS = %s' % (self.ToolChainFamily, self.BuildTarget, self.ToolChain, self.Arch, Item, self.BuildOption[Item]['FLAGS'].strip())]
3149
3150 AsBuiltInf = TemplateString()
3151 AsBuiltInf.Append(gAsBuiltInfHeaderString.Replace(AsBuiltInfDict))
3152
3153 SaveFileOnChange(os.path.join(self.OutputDir, self.Name + '.inf'), str(AsBuiltInf), False)
3154
3155 self.IsAsBuiltInfCreated = True
3156
3157 ## Create makefile for the module and its dependent libraries
3158 #
3159 # @param CreateLibraryMakeFile Flag indicating if or not the makefiles of
3160 # dependent libraries will be created
3161 #
3162 def CreateMakeFile(self, CreateLibraryMakeFile=True):
3163 # Ignore generating makefile when it is a binary module
3164 if self.IsBinaryModule:
3165 return
3166
3167 if self.IsMakeFileCreated:
3168 return
3169
3170 if not self.IsLibrary and CreateLibraryMakeFile:
3171 for LibraryAutoGen in self.LibraryAutoGenList:
3172 LibraryAutoGen.CreateMakeFile()
3173
3174 if len(self.CustomMakefile) == 0:
3175 Makefile = GenMake.ModuleMakefile(self)
3176 else:
3177 Makefile = GenMake.CustomMakefile(self)
3178 if Makefile.Generate():
3179 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated makefile for module %s [%s]" %
3180 (self.Name, self.Arch))
3181 else:
3182 EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of makefile for module %s [%s]" %
3183 (self.Name, self.Arch))
3184
3185 self.IsMakeFileCreated = True
3186
3187 def CopyBinaryFiles(self):
3188 for File in self.Module.Binaries:
3189 SrcPath = File.Path
3190 DstPath = os.path.join(self.OutputDir , os.path.basename(SrcPath))
3191 CopyLongFilePath(SrcPath, DstPath)
3192 ## Create autogen code for the module and its dependent libraries
3193 #
3194 # @param CreateLibraryCodeFile Flag indicating if or not the code of
3195 # dependent libraries will be created
3196 #
3197 def CreateCodeFile(self, CreateLibraryCodeFile=True):
3198 if self.IsCodeFileCreated:
3199 return
3200
3201 # Need to generate PcdDatabase even PcdDriver is binarymodule
3202 if self.IsBinaryModule and self.PcdIsDriver != '':
3203 CreatePcdDatabaseCode(self, TemplateString(), TemplateString())
3204 return
3205 if self.IsBinaryModule:
3206 self.CopyBinaryFiles()
3207 return
3208
3209 if not self.IsLibrary and CreateLibraryCodeFile:
3210 for LibraryAutoGen in self.LibraryAutoGenList:
3211 LibraryAutoGen.CreateCodeFile()
3212
3213 AutoGenList = []
3214 IgoredAutoGenList = []
3215
3216 for File in self.AutoGenFileList:
3217 if GenC.Generate(File.Path, self.AutoGenFileList[File], File.IsBinary):
3218 #Ignore Edk AutoGen.c
3219 if self.AutoGenVersion < 0x00010005 and File.Name == 'AutoGen.c':
3220 continue
3221
3222 AutoGenList.append(str(File))
3223 else:
3224 IgoredAutoGenList.append(str(File))
3225
3226 # Skip the following code for EDK I inf
3227 if self.AutoGenVersion < 0x00010005:
3228 return
3229
3230 for ModuleType in self.DepexList:
3231 # Ignore empty [depex] section or [depex] section for "USER_DEFINED" module
3232 if len(self.DepexList[ModuleType]) == 0 or ModuleType == "USER_DEFINED":
3233 continue
3234
3235 Dpx = GenDepex.DependencyExpression(self.DepexList[ModuleType], ModuleType, True)
3236 DpxFile = gAutoGenDepexFileName % {"module_name" : self.Name}
3237
3238 if len(Dpx.PostfixNotation) <> 0:
3239 self.DepexGenerated = True
3240
3241 if Dpx.Generate(path.join(self.OutputDir, DpxFile)):
3242 AutoGenList.append(str(DpxFile))
3243 else:
3244 IgoredAutoGenList.append(str(DpxFile))
3245
3246 if IgoredAutoGenList == []:
3247 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated [%s] files for module %s [%s]" %
3248 (" ".join(AutoGenList), self.Name, self.Arch))
3249 elif AutoGenList == []:
3250 EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of [%s] files for module %s [%s]" %
3251 (" ".join(IgoredAutoGenList), self.Name, self.Arch))
3252 else:
3253 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated [%s] (skipped %s) files for module %s [%s]" %
3254 (" ".join(AutoGenList), " ".join(IgoredAutoGenList), self.Name, self.Arch))
3255
3256 self.IsCodeFileCreated = True
3257 return AutoGenList
3258
3259 ## Summarize the ModuleAutoGen objects of all libraries used by this module
3260 def _GetLibraryAutoGenList(self):
3261 if self._LibraryAutoGenList == None:
3262 self._LibraryAutoGenList = []
3263 for Library in self.DependentLibraryList:
3264 La = ModuleAutoGen(
3265 self.Workspace,
3266 Library.MetaFile,
3267 self.BuildTarget,
3268 self.ToolChain,
3269 self.Arch,
3270 self.PlatformInfo.MetaFile
3271 )
3272 if La not in self._LibraryAutoGenList:
3273 self._LibraryAutoGenList.append(La)
3274 for Lib in La.CodaTargetList:
3275 self._ApplyBuildRule(Lib.Target, TAB_UNKNOWN_FILE)
3276 return self._LibraryAutoGenList
3277
3278 Module = property(_GetModule)
3279 Name = property(_GetBaseName)
3280 Guid = property(_GetGuid)
3281 Version = property(_GetVersion)
3282 ModuleType = property(_GetModuleType)
3283 ComponentType = property(_GetComponentType)
3284 BuildType = property(_GetBuildType)
3285 PcdIsDriver = property(_GetPcdIsDriver)
3286 AutoGenVersion = property(_GetAutoGenVersion)
3287 Macros = property(_GetMacros)
3288 Specification = property(_GetSpecification)
3289
3290 IsLibrary = property(_IsLibrary)
3291 IsBinaryModule = property(_IsBinaryModule)
3292 BuildDir = property(_GetBuildDir)
3293 OutputDir = property(_GetOutputDir)
3294 DebugDir = property(_GetDebugDir)
3295 MakeFileDir = property(_GetMakeFileDir)
3296 CustomMakefile = property(_GetCustomMakefile)
3297
3298 IncludePathList = property(_GetIncludePathList)
3299 AutoGenFileList = property(_GetAutoGenFileList)
3300 UnicodeFileList = property(_GetUnicodeFileList)
3301 SourceFileList = property(_GetSourceFileList)
3302 BinaryFileList = property(_GetBinaryFiles) # FileType : [File List]
3303 Targets = property(_GetTargets)
3304 IntroTargetList = property(_GetIntroTargetList)
3305 CodaTargetList = property(_GetFinalTargetList)
3306 FileTypes = property(_GetFileTypes)
3307 BuildRules = property(_GetBuildRules)
3308
3309 DependentPackageList = property(_GetDependentPackageList)
3310 DependentLibraryList = property(_GetLibraryList)
3311 LibraryAutoGenList = property(_GetLibraryAutoGenList)
3312 DerivedPackageList = property(_GetDerivedPackageList)
3313
3314 ModulePcdList = property(_GetModulePcdList)
3315 LibraryPcdList = property(_GetLibraryPcdList)
3316 GuidList = property(_GetGuidList)
3317 ProtocolList = property(_GetProtocolList)
3318 PpiList = property(_GetPpiList)
3319 DepexList = property(_GetDepexTokenList)
3320 DxsFile = property(_GetDxsFile)
3321 DepexExpressionList = property(_GetDepexExpressionTokenList)
3322 BuildOption = property(_GetModuleBuildOption)
3323 BuildOptionIncPathList = property(_GetBuildOptionIncPathList)
3324 BuildCommand = property(_GetBuildCommand)
3325
3326 FixedAtBuildPcds = property(_GetFixedAtBuildPcds)
3327
3328 # This acts like the main() function for the script, unless it is 'import'ed into another script.
3329 if __name__ == '__main__':
3330 pass
3331