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