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