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