]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/AutoGen/AutoGen.py
Sync EDKII BaseTools to BaseTools project r1937.
[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 - 2010, Intel Corporation
5 # All rights reserved. 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
38 ## Regular expression for splitting Dependency Expression stirng into tokens
39 gDepexTokenPattern = re.compile("(\(|\)|\w+| \S+\.inf)")
40
41 ## Mapping Makefile type
42 gMakeTypeMap = {"MSFT":"nmake", "GCC":"gmake"}
43
44
45 ## Build rule configuration file
46 gBuildRuleFile = 'Conf/build_rule.txt'
47
48 ## default file name for AutoGen
49 gAutoGenCodeFileName = "AutoGen.c"
50 gAutoGenHeaderFileName = "AutoGen.h"
51 gAutoGenStringFileName = "%(module_name)sStrDefs.h"
52 gAutoGenStringFormFileName = "%(module_name)sStrDefs.hpk"
53 gAutoGenDepexFileName = "%(module_name)s.depex"
54
55 ## Base class for AutoGen
56 #
57 # This class just implements the cache mechanism of AutoGen objects.
58 #
59 class AutoGen(object):
60 # database to maintain the objects of xxxAutoGen
61 _CACHE_ = {} # (BuildTarget, ToolChain) : {ARCH : {platform file: AutoGen object}}}
62
63 ## Factory method
64 #
65 # @param Class class object of real AutoGen class
66 # (WorkspaceAutoGen, ModuleAutoGen or PlatformAutoGen)
67 # @param Workspace Workspace directory or WorkspaceAutoGen object
68 # @param MetaFile The path of meta file
69 # @param Target Build target
70 # @param Toolchain Tool chain name
71 # @param Arch Target arch
72 # @param *args The specific class related parameters
73 # @param **kwargs The specific class related dict parameters
74 #
75 def __new__(Class, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):
76 # check if the object has been created
77 Key = (Target, Toolchain)
78 if Key not in Class._CACHE_ or Arch not in Class._CACHE_[Key] \
79 or MetaFile not in Class._CACHE_[Key][Arch]:
80 AutoGenObject = super(AutoGen, Class).__new__(Class)
81 # call real constructor
82 if not AutoGenObject._Init(Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):
83 return None
84 if Key not in Class._CACHE_:
85 Class._CACHE_[Key] = {}
86 if Arch not in Class._CACHE_[Key]:
87 Class._CACHE_[Key][Arch] = {}
88 Class._CACHE_[Key][Arch][MetaFile] = AutoGenObject
89 else:
90 AutoGenObject = Class._CACHE_[Key][Arch][MetaFile]
91
92 return AutoGenObject
93
94 ## hash() operator
95 #
96 # The file path of platform file will be used to represent hash value of this object
97 #
98 # @retval int Hash value of the file path of platform file
99 #
100 def __hash__(self):
101 return hash(self.MetaFile)
102
103 ## str() operator
104 #
105 # The file path of platform file will be used to represent this object
106 #
107 # @retval string String of platform file path
108 #
109 def __str__(self):
110 return str(self.MetaFile)
111
112 ## "==" operator
113 def __eq__(self, Other):
114 return Other and self.MetaFile == Other
115
116 ## Workspace AutoGen class
117 #
118 # This class is used mainly to control the whole platform build for different
119 # architecture. This class will generate top level makefile.
120 #
121 class WorkspaceAutoGen(AutoGen):
122 ## Real constructor of WorkspaceAutoGen
123 #
124 # This method behaves the same as __init__ except that it needs explict invoke
125 # (in super class's __new__ method)
126 #
127 # @param WorkspaceDir Root directory of workspace
128 # @param ActivePlatform Meta-file of active platform
129 # @param Target Build target
130 # @param Toolchain Tool chain name
131 # @param ArchList List of architecture of current build
132 # @param MetaFileDb Database containing meta-files
133 # @param BuildConfig Configuration of build
134 # @param ToolDefinition Tool chain definitions
135 # @param FlashDefinitionFile File of flash definition
136 # @param Fds FD list to be generated
137 # @param Fvs FV list to be generated
138 # @param SkuId SKU id from command line
139 #
140 def _Init(self, WorkspaceDir, ActivePlatform, Target, Toolchain, ArchList, MetaFileDb,
141 BuildConfig, ToolDefinition, FlashDefinitionFile='', Fds=[], Fvs=[], SkuId='', UniFlag=None):
142 self.MetaFile = ActivePlatform.MetaFile
143 self.WorkspaceDir = WorkspaceDir
144 self.Platform = ActivePlatform
145 self.BuildTarget = Target
146 self.ToolChain = Toolchain
147 self.ArchList = ArchList
148 self.SkuId = SkuId
149 self.UniFlag = UniFlag
150
151 self.BuildDatabase = MetaFileDb
152 self.TargetTxt = BuildConfig
153 self.ToolDef = ToolDefinition
154 self.FdfFile = FlashDefinitionFile
155 self.FdTargetList = Fds
156 self.FvTargetList = Fvs
157 self.AutoGenObjectList = []
158
159 # there's many relative directory operations, so ...
160 os.chdir(self.WorkspaceDir)
161
162 # parse FDF file to get PCDs in it, if any
163 if self.FdfFile != None and self.FdfFile != '':
164 Fdf = FdfParser(self.FdfFile.Path)
165 Fdf.ParseFile()
166 PcdSet = Fdf.Profile.PcdDict
167 ModuleList = Fdf.Profile.InfList
168 self.FdfProfile = Fdf.Profile
169 else:
170 PcdSet = {}
171 ModuleList = []
172 self.FdfProfile = None
173
174 # apply SKU and inject PCDs from Flash Definition file
175 for Arch in self.ArchList:
176 Platform = self.BuildDatabase[self.MetaFile, Arch]
177 Platform.SkuName = self.SkuId
178 for Name, Guid in PcdSet:
179 Platform.AddPcd(Name, Guid, PcdSet[Name, Guid])
180
181 Pa = PlatformAutoGen(self, self.MetaFile, Target, Toolchain, Arch)
182 #
183 # Explicitly collect platform's dynamic PCDs
184 #
185 Pa.CollectPlatformDynamicPcds()
186 self.AutoGenObjectList.append(Pa)
187
188 self._BuildDir = None
189 self._FvDir = None
190 self._MakeFileDir = None
191 self._BuildCommand = None
192
193 return True
194
195 def __repr__(self):
196 return "%s [%s]" % (self.MetaFile, ", ".join(self.ArchList))
197
198 ## Return the directory to store FV files
199 def _GetFvDir(self):
200 if self._FvDir == None:
201 self._FvDir = path.join(self.BuildDir, 'FV')
202 return self._FvDir
203
204 ## Return the directory to store all intermediate and final files built
205 def _GetBuildDir(self):
206 return self.AutoGenObjectList[0].BuildDir
207
208 ## Return the build output directory platform specifies
209 def _GetOutputDir(self):
210 return self.Platform.OutputDirectory
211
212 ## Return platform name
213 def _GetName(self):
214 return self.Platform.PlatformName
215
216 ## Return meta-file GUID
217 def _GetGuid(self):
218 return self.Platform.Guid
219
220 ## Return platform version
221 def _GetVersion(self):
222 return self.Platform.Version
223
224 ## Return paths of tools
225 def _GetToolDefinition(self):
226 return self.AutoGenObjectList[0].ToolDefinition
227
228 ## Return directory of platform makefile
229 #
230 # @retval string Makefile directory
231 #
232 def _GetMakeFileDir(self):
233 if self._MakeFileDir == None:
234 self._MakeFileDir = self.BuildDir
235 return self._MakeFileDir
236
237 ## Return build command string
238 #
239 # @retval string Build command string
240 #
241 def _GetBuildCommand(self):
242 if self._BuildCommand == None:
243 # BuildCommand should be all the same. So just get one from platform AutoGen
244 self._BuildCommand = self.AutoGenObjectList[0].BuildCommand
245 return self._BuildCommand
246
247 ## Create makefile for the platform and mdoules in it
248 #
249 # @param CreateDepsMakeFile Flag indicating if the makefile for
250 # modules will be created as well
251 #
252 def CreateMakeFile(self, CreateDepsMakeFile=False):
253 # create makefile for platform
254 Makefile = GenMake.TopLevelMakefile(self)
255 if Makefile.Generate():
256 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated makefile for platform [%s] %s\n" %
257 (self.MetaFile, self.ArchList))
258 else:
259 EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of makefile for platform [%s] %s\n" %
260 (self.MetaFile, self.ArchList))
261
262 if CreateDepsMakeFile:
263 for Pa in self.AutoGenObjectList:
264 Pa.CreateMakeFile(CreateDepsMakeFile)
265
266 ## Create autogen code for platform and modules
267 #
268 # Since there's no autogen code for platform, this method will do nothing
269 # if CreateModuleCodeFile is set to False.
270 #
271 # @param CreateDepsCodeFile Flag indicating if creating module's
272 # autogen code file or not
273 #
274 def CreateCodeFile(self, CreateDepsCodeFile=False):
275 if not CreateDepsCodeFile:
276 return
277 for Pa in self.AutoGenObjectList:
278 Pa.CreateCodeFile(CreateDepsCodeFile)
279
280 Name = property(_GetName)
281 Guid = property(_GetGuid)
282 Version = property(_GetVersion)
283 OutputDir = property(_GetOutputDir)
284
285 ToolDefinition = property(_GetToolDefinition) # toolcode : tool path
286
287 BuildDir = property(_GetBuildDir)
288 FvDir = property(_GetFvDir)
289 MakeFileDir = property(_GetMakeFileDir)
290 BuildCommand = property(_GetBuildCommand)
291
292 ## AutoGen class for platform
293 #
294 # PlatformAutoGen class will process the original information in platform
295 # file in order to generate makefile for platform.
296 #
297 class PlatformAutoGen(AutoGen):
298 #
299 # Used to store all PCDs for both PEI and DXE phase, in order to generate
300 # correct PCD database
301 #
302 _DynaPcdList_ = []
303 _NonDynaPcdList_ = []
304
305 ## The real constructor of PlatformAutoGen
306 #
307 # This method is not supposed to be called by users of PlatformAutoGen. It's
308 # only used by factory method __new__() to do real initialization work for an
309 # object of PlatformAutoGen
310 #
311 # @param Workspace WorkspaceAutoGen object
312 # @param PlatformFile Platform file (DSC file)
313 # @param Target Build target (DEBUG, RELEASE)
314 # @param Toolchain Name of tool chain
315 # @param Arch arch of the platform supports
316 #
317 def _Init(self, Workspace, PlatformFile, Target, Toolchain, Arch):
318 EdkLogger.debug(EdkLogger.DEBUG_9, "AutoGen platform [%s] [%s]" % (PlatformFile, Arch))
319 GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (PlatformFile, Arch, Toolchain, Target)
320
321 self.MetaFile = PlatformFile
322 self.Workspace = Workspace
323 self.WorkspaceDir = Workspace.WorkspaceDir
324 self.ToolChain = Toolchain
325 self.BuildTarget = Target
326 self.Arch = Arch
327 self.SourceDir = PlatformFile.SubDir
328 self.SourceOverrideDir = None
329 self.FdTargetList = self.Workspace.FdTargetList
330 self.FvTargetList = self.Workspace.FvTargetList
331 self.AllPcdList = []
332
333 # flag indicating if the makefile/C-code file has been created or not
334 self.IsMakeFileCreated = False
335 self.IsCodeFileCreated = False
336
337 self._Platform = None
338 self._Name = None
339 self._Guid = None
340 self._Version = None
341
342 self._BuildRule = None
343 self._SourceDir = None
344 self._BuildDir = None
345 self._OutputDir = None
346 self._FvDir = None
347 self._MakeFileDir = None
348 self._FdfFile = None
349
350 self._PcdTokenNumber = None # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
351 self._DynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
352 self._NonDynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
353
354 self._ToolDefinitions = None
355 self._ToolDefFile = None # toolcode : tool path
356 self._ToolChainFamily = None
357 self._BuildRuleFamily = None
358 self._BuildOption = None # toolcode : option
359 self._EdkBuildOption = None # edktoolcode : option
360 self._EdkIIBuildOption = None # edkiitoolcode : option
361 self._PackageList = None
362 self._ModuleAutoGenList = None
363 self._LibraryAutoGenList = None
364 self._BuildCommand = None
365
366 # get the original module/package/platform objects
367 self.BuildDatabase = Workspace.BuildDatabase
368 return True
369
370 def __repr__(self):
371 return "%s [%s]" % (self.MetaFile, self.Arch)
372
373 ## Create autogen code for platform and modules
374 #
375 # Since there's no autogen code for platform, this method will do nothing
376 # if CreateModuleCodeFile is set to False.
377 #
378 # @param CreateModuleCodeFile Flag indicating if creating module's
379 # autogen code file or not
380 #
381 def CreateCodeFile(self, CreateModuleCodeFile=False):
382 # only module has code to be greated, so do nothing if CreateModuleCodeFile is False
383 if self.IsCodeFileCreated or not CreateModuleCodeFile:
384 return
385
386 for Ma in self.ModuleAutoGenList:
387 Ma.CreateCodeFile(True)
388
389 # don't do this twice
390 self.IsCodeFileCreated = True
391
392 ## Create makefile for the platform and mdoules in it
393 #
394 # @param CreateModuleMakeFile Flag indicating if the makefile for
395 # modules will be created as well
396 #
397 def CreateMakeFile(self, CreateModuleMakeFile=False):
398 if CreateModuleMakeFile:
399 for ModuleFile in self.Platform.Modules:
400 Ma = ModuleAutoGen(self.Workspace, ModuleFile, self.BuildTarget,
401 self.ToolChain, self.Arch, self.MetaFile)
402 Ma.CreateMakeFile(True)
403
404 # no need to create makefile for the platform more than once
405 if self.IsMakeFileCreated:
406 return
407
408 # create makefile for platform
409 Makefile = GenMake.PlatformMakefile(self)
410 if Makefile.Generate():
411 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated makefile for platform [%s] [%s]\n" %
412 (self.MetaFile, self.Arch))
413 else:
414 EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of makefile for platform [%s] [%s]\n" %
415 (self.MetaFile, self.Arch))
416 self.IsMakeFileCreated = True
417
418 ## Collect dynamic PCDs
419 #
420 # Gather dynamic PCDs list from each module and their settings from platform
421 # This interface should be invoked explicitly when platform action is created.
422 #
423 def CollectPlatformDynamicPcds(self):
424 # for gathering error information
425 NoDatumTypePcdList = set()
426
427 self._GuidValue = {}
428 for F in self.Platform.Modules.keys():
429 M = ModuleAutoGen(self.Workspace, F, self.BuildTarget, self.ToolChain, self.Arch, self.MetaFile)
430 #GuidValue.update(M.Guids)
431
432 self.Platform.Modules[F].M = M
433
434 for PcdFromModule in M.ModulePcdList+M.LibraryPcdList:
435 # make sure that the "VOID*" kind of datum has MaxDatumSize set
436 if PcdFromModule.DatumType == "VOID*" and PcdFromModule.MaxDatumSize == None:
437 NoDatumTypePcdList.add("%s.%s [%s]" % (PcdFromModule.TokenSpaceGuidCName, PcdFromModule.TokenCName, F))
438
439 if PcdFromModule.Type in GenC.gDynamicPcd or PcdFromModule.Type in GenC.gDynamicExPcd:
440 #
441 # If a dynamic PCD used by a PEM module/PEI module & DXE module,
442 # it should be stored in Pcd PEI database, If a dynamic only
443 # used by DXE module, it should be stored in DXE PCD database.
444 # The default Phase is DXE
445 #
446 if M.ModuleType in ["PEIM", "PEI_CORE"]:
447 PcdFromModule.Phase = "PEI"
448 if PcdFromModule not in self._DynaPcdList_:
449 self._DynaPcdList_.append(PcdFromModule)
450 elif PcdFromModule.Phase == 'PEI':
451 # overwrite any the same PCD existing, if Phase is PEI
452 Index = self._DynaPcdList_.index(PcdFromModule)
453 self._DynaPcdList_[Index] = PcdFromModule
454 elif PcdFromModule not in self._NonDynaPcdList_:
455 self._NonDynaPcdList_.append(PcdFromModule)
456
457 # print out error information and break the build, if error found
458 if len(NoDatumTypePcdList) > 0:
459 NoDatumTypePcdListString = "\n\t\t".join(NoDatumTypePcdList)
460 EdkLogger.error("build", AUTOGEN_ERROR, "PCD setting error",
461 File=self.MetaFile,
462 ExtraData="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"
463 % NoDatumTypePcdListString)
464 self._NonDynamicPcdList = self._NonDynaPcdList_
465 self._DynamicPcdList = self._DynaPcdList_
466 self.AllPcdList = self._NonDynamicPcdList + self._DynamicPcdList
467
468 #
469 # Sort dynamic PCD list to:
470 # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should
471 # try to be put header of dynamicd List
472 # 2) If PCD is HII type, the PCD item should be put after unicode type PCD
473 #
474 # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.
475 #
476 UnicodePcdArray = []
477 HiiPcdArray = []
478 OtherPcdArray = []
479 for Pcd in self._DynamicPcdList:
480 # just pick the a value to determine whether is unicode string type
481 Sku = Pcd.SkuInfoList[Pcd.SkuInfoList.keys()[0]]
482 PcdValue = Sku.DefaultValue
483 if Pcd.DatumType == 'VOID*' and PcdValue.startswith("L"):
484 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
485 UnicodePcdArray.append(Pcd)
486 elif len(Sku.VariableName) > 0:
487 # if found HII type PCD then insert to right of UnicodeIndex
488 HiiPcdArray.append(Pcd)
489 else:
490 OtherPcdArray.append(Pcd)
491 del self._DynamicPcdList[:]
492 self._DynamicPcdList.extend(UnicodePcdArray)
493 self._DynamicPcdList.extend(HiiPcdArray)
494 self._DynamicPcdList.extend(OtherPcdArray)
495
496
497 ## Return the platform build data object
498 def _GetPlatform(self):
499 if self._Platform == None:
500 self._Platform = self.BuildDatabase[self.MetaFile, self.Arch]
501 return self._Platform
502
503 ## Return platform name
504 def _GetName(self):
505 return self.Platform.PlatformName
506
507 ## Return the meta file GUID
508 def _GetGuid(self):
509 return self.Platform.Guid
510
511 ## Return the platform version
512 def _GetVersion(self):
513 return self.Platform.Version
514
515 ## Return the FDF file name
516 def _GetFdfFile(self):
517 if self._FdfFile == None:
518 if self.Workspace.FdfFile != "":
519 self._FdfFile= path.join(self.WorkspaceDir, self.Workspace.FdfFile)
520 else:
521 self._FdfFile = ''
522 return self._FdfFile
523
524 ## Return the build output directory platform specifies
525 def _GetOutputDir(self):
526 return self.Platform.OutputDirectory
527
528 ## Return the directory to store all intermediate and final files built
529 def _GetBuildDir(self):
530 if self._BuildDir == None:
531 if os.path.isabs(self.OutputDir):
532 self._BuildDir = path.join(
533 path.abspath(self.OutputDir),
534 self.BuildTarget + "_" + self.ToolChain,
535 )
536 else:
537 self._BuildDir = path.join(
538 self.WorkspaceDir,
539 self.OutputDir,
540 self.BuildTarget + "_" + self.ToolChain,
541 )
542 return self._BuildDir
543
544 ## Return directory of platform makefile
545 #
546 # @retval string Makefile directory
547 #
548 def _GetMakeFileDir(self):
549 if self._MakeFileDir == None:
550 self._MakeFileDir = path.join(self.BuildDir, self.Arch)
551 return self._MakeFileDir
552
553 ## Return build command string
554 #
555 # @retval string Build command string
556 #
557 def _GetBuildCommand(self):
558 if self._BuildCommand == None:
559 self._BuildCommand = []
560 if "MAKE" in self.ToolDefinition and "PATH" in self.ToolDefinition["MAKE"]:
561 self._BuildCommand += SplitOption(self.ToolDefinition["MAKE"]["PATH"])
562 if "FLAGS" in self.ToolDefinition["MAKE"]:
563 NewOption = self.ToolDefinition["MAKE"]["FLAGS"].strip()
564 if NewOption != '':
565 self._BuildCommand += SplitOption(NewOption)
566 return self._BuildCommand
567
568 ## Get tool chain definition
569 #
570 # Get each tool defition for given tool chain from tools_def.txt and platform
571 #
572 def _GetToolDefinition(self):
573 if self._ToolDefinitions == None:
574 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDictionary
575 if TAB_TOD_DEFINES_COMMAND_TYPE not in self.Workspace.ToolDef.ToolsDefTxtDatabase:
576 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "No tools found in configuration",
577 ExtraData="[%s]" % self.MetaFile)
578 self._ToolDefinitions = {}
579 DllPathList = set()
580 for Def in ToolDefinition:
581 Target, Tag, Arch, Tool, Attr = Def.split("_")
582 if Target != self.BuildTarget or Tag != self.ToolChain or Arch != self.Arch:
583 continue
584
585 Value = ToolDefinition[Def]
586 # don't record the DLL
587 if Attr == "DLL":
588 DllPathList.add(Value)
589 continue
590
591 if Tool not in self._ToolDefinitions:
592 self._ToolDefinitions[Tool] = {}
593 self._ToolDefinitions[Tool][Attr] = Value
594
595 ToolsDef = ''
596 MakePath = ''
597 if GlobalData.gOptions.SilentMode and "MAKE" in self._ToolDefinitions:
598 if "FLAGS" not in self._ToolDefinitions["MAKE"]:
599 self._ToolDefinitions["MAKE"]["FLAGS"] = ""
600 self._ToolDefinitions["MAKE"]["FLAGS"] += " -s"
601 MakeFlags = ''
602 for Tool in self._ToolDefinitions:
603 for Attr in self._ToolDefinitions[Tool]:
604 Value = self._ToolDefinitions[Tool][Attr]
605 if Tool in self.BuildOption and Attr in self.BuildOption[Tool]:
606 # check if override is indicated
607 if self.BuildOption[Tool][Attr].startswith('='):
608 Value = self.BuildOption[Tool][Attr][1:]
609 else:
610 Value += " " + self.BuildOption[Tool][Attr]
611
612 if Attr == "PATH":
613 # Don't put MAKE definition in the file
614 if Tool == "MAKE":
615 MakePath = Value
616 else:
617 ToolsDef += "%s = %s\n" % (Tool, Value)
618 elif Attr != "DLL":
619 # Don't put MAKE definition in the file
620 if Tool == "MAKE":
621 if Attr == "FLAGS":
622 MakeFlags = Value
623 else:
624 ToolsDef += "%s_%s = %s\n" % (Tool, Attr, Value)
625 ToolsDef += "\n"
626
627 SaveFileOnChange(self.ToolDefinitionFile, ToolsDef)
628 for DllPath in DllPathList:
629 os.environ["PATH"] = DllPath + os.pathsep + os.environ["PATH"]
630 os.environ["MAKE_FLAGS"] = MakeFlags
631
632 return self._ToolDefinitions
633
634 ## Return the paths of tools
635 def _GetToolDefFile(self):
636 if self._ToolDefFile == None:
637 self._ToolDefFile = os.path.join(self.MakeFileDir, "TOOLS_DEF." + self.Arch)
638 return self._ToolDefFile
639
640 ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
641 def _GetToolChainFamily(self):
642 if self._ToolChainFamily == None:
643 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase
644 if TAB_TOD_DEFINES_FAMILY not in ToolDefinition \
645 or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_FAMILY] \
646 or not ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]:
647 EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
648 % self.ToolChain)
649 self._ToolChainFamily = "MSFT"
650 else:
651 self._ToolChainFamily = ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]
652 return self._ToolChainFamily
653
654 def _GetBuildRuleFamily(self):
655 if self._BuildRuleFamily == None:
656 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase
657 if TAB_TOD_DEFINES_BUILDRULEFAMILY not in ToolDefinition \
658 or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY] \
659 or not ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]:
660 EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
661 % self.ToolChain)
662 self._BuildRuleFamily = "MSFT"
663 else:
664 self._BuildRuleFamily = ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]
665 return self._BuildRuleFamily
666
667 ## Return the build options specific for all modules in this platform
668 def _GetBuildOptions(self):
669 if self._BuildOption == None:
670 self._BuildOption = self._ExpandBuildOption(self.Platform.BuildOptions)
671 return self._BuildOption
672
673 ## Return the build options specific for EDK modules in this platform
674 def _GetEdkBuildOptions(self):
675 if self._EdkBuildOption == None:
676 self._EdkBuildOption = self._ExpandBuildOption(self.Platform.BuildOptions, EDK_NAME)
677 return self._EdkBuildOption
678
679 ## Return the build options specific for EDKII modules in this platform
680 def _GetEdkIIBuildOptions(self):
681 if self._EdkIIBuildOption == None:
682 self._EdkIIBuildOption = self._ExpandBuildOption(self.Platform.BuildOptions, EDKII_NAME)
683 return self._EdkIIBuildOption
684
685 ## Parse build_rule.txt in $(WORKSPACE)/Conf/build_rule.txt
686 #
687 # @retval BuildRule object
688 #
689 def _GetBuildRule(self):
690 if self._BuildRule == None:
691 BuildRuleFile = None
692 if TAB_TAT_DEFINES_BUILD_RULE_CONF in self.Workspace.TargetTxt.TargetTxtDictionary:
693 BuildRuleFile = self.Workspace.TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_BUILD_RULE_CONF]
694 if BuildRuleFile in [None, '']:
695 BuildRuleFile = gBuildRuleFile
696 self._BuildRule = BuildRule(BuildRuleFile)
697 return self._BuildRule
698
699 ## Summarize the packages used by modules in this platform
700 def _GetPackageList(self):
701 if self._PackageList == None:
702 self._PackageList = set()
703 for La in self.LibraryAutoGenList:
704 self._PackageList.update(La.DependentPackageList)
705 for Ma in self.ModuleAutoGenList:
706 self._PackageList.update(Ma.DependentPackageList)
707 self._PackageList = list(self._PackageList)
708 return self._PackageList
709
710 ## Get list of non-dynamic PCDs
711 def _GetNonDynamicPcdList(self):
712 return self._NonDynamicPcdList
713
714 ## Get list of dynamic PCDs
715 def _GetDynamicPcdList(self):
716 return self._DynamicPcdList
717
718 ## Generate Token Number for all PCD
719 def _GetPcdTokenNumbers(self):
720 if self._PcdTokenNumber == None:
721 self._PcdTokenNumber = sdict()
722 TokenNumber = 1
723 for Pcd in self.DynamicPcdList:
724 if Pcd.Phase == "PEI":
725 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
726 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
727 TokenNumber += 1
728
729 for Pcd in self.DynamicPcdList:
730 if Pcd.Phase == "DXE":
731 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
732 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
733 TokenNumber += 1
734
735 for Pcd in self.NonDynamicPcdList:
736 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
737 TokenNumber += 1
738 return self._PcdTokenNumber
739
740 ## Summarize ModuleAutoGen objects of all modules/libraries to be built for this platform
741 def _GetAutoGenObjectList(self):
742 self._ModuleAutoGenList = []
743 self._LibraryAutoGenList = []
744 for ModuleFile in self.Platform.Modules:
745 Ma = ModuleAutoGen(
746 self.Workspace,
747 ModuleFile,
748 self.BuildTarget,
749 self.ToolChain,
750 self.Arch,
751 self.MetaFile
752 )
753 if Ma not in self._ModuleAutoGenList:
754 self._ModuleAutoGenList.append(Ma)
755 for La in Ma.LibraryAutoGenList:
756 if La not in self._LibraryAutoGenList:
757 self._LibraryAutoGenList.append(La)
758
759 ## Summarize ModuleAutoGen objects of all modules to be built for this platform
760 def _GetModuleAutoGenList(self):
761 if self._ModuleAutoGenList == None:
762 self._GetAutoGenObjectList()
763 return self._ModuleAutoGenList
764
765 ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
766 def _GetLibraryAutoGenList(self):
767 if self._LibraryAutoGenList == None:
768 self._GetAutoGenObjectList()
769 return self._LibraryAutoGenList
770
771 ## Test if a module is supported by the platform
772 #
773 # An error will be raised directly if the module or its arch is not supported
774 # by the platform or current configuration
775 #
776 def ValidModule(self, Module):
777 return Module in self.Platform.Modules or Module in self.Platform.LibraryInstances
778
779 ## Resolve the library classes in a module to library instances
780 #
781 # This method will not only resolve library classes but also sort the library
782 # instances according to the dependency-ship.
783 #
784 # @param Module The module from which the library classes will be resolved
785 #
786 # @retval library_list List of library instances sorted
787 #
788 def ApplyLibraryInstance(self, Module):
789 ModuleType = Module.ModuleType
790
791 # for overridding library instances with module specific setting
792 PlatformModule = self.Platform.Modules[str(Module)]
793
794 # add forced library instances (specified under LibraryClasses sections)
795 for LibraryClass in self.Platform.LibraryClasses.GetKeys():
796 if LibraryClass.startswith("NULL"):
797 Module.LibraryClasses[LibraryClass] = self.Platform.LibraryClasses[LibraryClass]
798
799 # add forced library instances (specified in module overrides)
800 for LibraryClass in PlatformModule.LibraryClasses:
801 if LibraryClass.startswith("NULL"):
802 Module.LibraryClasses[LibraryClass] = PlatformModule.LibraryClasses[LibraryClass]
803
804 # R9 module
805 LibraryConsumerList = [Module]
806 Constructor = []
807 ConsumedByList = sdict()
808 LibraryInstance = sdict()
809
810 EdkLogger.verbose("")
811 EdkLogger.verbose("Library instances of module [%s] [%s]:" % (str(Module), self.Arch))
812 while len(LibraryConsumerList) > 0:
813 M = LibraryConsumerList.pop()
814 for LibraryClassName in M.LibraryClasses:
815 if LibraryClassName not in LibraryInstance:
816 # override library instance for this module
817 if LibraryClassName in PlatformModule.LibraryClasses:
818 LibraryPath = PlatformModule.LibraryClasses[LibraryClassName]
819 else:
820 LibraryPath = self.Platform.LibraryClasses[LibraryClassName, ModuleType]
821 if LibraryPath == None or LibraryPath == "":
822 LibraryPath = M.LibraryClasses[LibraryClassName]
823 if LibraryPath == None or LibraryPath == "":
824 EdkLogger.error("build", RESOURCE_NOT_AVAILABLE,
825 "Instance of library class [%s] is not found" % LibraryClassName,
826 File=self.MetaFile,
827 ExtraData="in [%s] [%s]\n\tconsumed by module [%s]" % (str(M), self.Arch, str(Module)))
828
829 LibraryModule = self.BuildDatabase[LibraryPath, self.Arch]
830 # for those forced library instance (NULL library), add a fake library class
831 if LibraryClassName.startswith("NULL"):
832 LibraryModule.LibraryClass.append(LibraryClassObject(LibraryClassName, [ModuleType]))
833 elif LibraryModule.LibraryClass == None \
834 or len(LibraryModule.LibraryClass) == 0 \
835 or (ModuleType != 'USER_DEFINED'
836 and ModuleType not in LibraryModule.LibraryClass[0].SupModList):
837 # only USER_DEFINED can link against any library instance despite of its SupModList
838 EdkLogger.error("build", OPTION_MISSING,
839 "Module type [%s] is not supported by library instance [%s]" \
840 % (ModuleType, LibraryPath), File=self.MetaFile,
841 ExtraData="consumed by [%s]" % str(Module))
842
843 LibraryInstance[LibraryClassName] = LibraryModule
844 LibraryConsumerList.append(LibraryModule)
845 EdkLogger.verbose("\t" + str(LibraryClassName) + " : " + str(LibraryModule))
846 else:
847 LibraryModule = LibraryInstance[LibraryClassName]
848
849 if LibraryModule == None:
850 continue
851
852 if LibraryModule.ConstructorList != [] and LibraryModule not in Constructor:
853 Constructor.append(LibraryModule)
854
855 if LibraryModule not in ConsumedByList:
856 ConsumedByList[LibraryModule] = []
857 # don't add current module itself to consumer list
858 if M != Module:
859 if M in ConsumedByList[LibraryModule]:
860 continue
861 ConsumedByList[LibraryModule].append(M)
862 #
863 # Initialize the sorted output list to the empty set
864 #
865 SortedLibraryList = []
866 #
867 # Q <- Set of all nodes with no incoming edges
868 #
869 LibraryList = [] #LibraryInstance.values()
870 Q = []
871 for LibraryClassName in LibraryInstance:
872 M = LibraryInstance[LibraryClassName]
873 LibraryList.append(M)
874 if ConsumedByList[M] == []:
875 Q.append(M)
876
877 #
878 # start the DAG algorithm
879 #
880 while True:
881 EdgeRemoved = True
882 while Q == [] and EdgeRemoved:
883 EdgeRemoved = False
884 # for each node Item with a Constructor
885 for Item in LibraryList:
886 if Item not in Constructor:
887 continue
888 # for each Node without a constructor with an edge e from Item to Node
889 for Node in ConsumedByList[Item]:
890 if Node in Constructor:
891 continue
892 # remove edge e from the graph if Node has no constructor
893 ConsumedByList[Item].remove(Node)
894 EdgeRemoved = True
895 if ConsumedByList[Item] == []:
896 # insert Item into Q
897 Q.insert(0, Item)
898 break
899 if Q != []:
900 break
901 # DAG is done if there's no more incoming edge for all nodes
902 if Q == []:
903 break
904
905 # remove node from Q
906 Node = Q.pop()
907 # output Node
908 SortedLibraryList.append(Node)
909
910 # for each node Item with an edge e from Node to Item do
911 for Item in LibraryList:
912 if Node not in ConsumedByList[Item]:
913 continue
914 # remove edge e from the graph
915 ConsumedByList[Item].remove(Node)
916
917 if ConsumedByList[Item] != []:
918 continue
919 # insert Item into Q, if Item has no other incoming edges
920 Q.insert(0, Item)
921
922 #
923 # if any remaining node Item in the graph has a constructor and an incoming edge, then the graph has a cycle
924 #
925 for Item in LibraryList:
926 if ConsumedByList[Item] != [] and Item in Constructor and len(Constructor) > 1:
927 ErrorMessage = "\tconsumed by " + "\n\tconsumed by ".join([str(L) for L in ConsumedByList[Item]])
928 EdkLogger.error("build", BUILD_ERROR, 'Library [%s] with constructors has a cycle' % str(Item),
929 ExtraData=ErrorMessage, File=self.MetaFile)
930 if Item not in SortedLibraryList:
931 SortedLibraryList.append(Item)
932
933 #
934 # Build the list of constructor and destructir names
935 # The DAG Topo sort produces the destructor order, so the list of constructors must generated in the reverse order
936 #
937 SortedLibraryList.reverse()
938 return SortedLibraryList
939
940
941 ## Override PCD setting (type, value, ...)
942 #
943 # @param ToPcd The PCD to be overrided
944 # @param FromPcd The PCD overrideing from
945 #
946 def _OverridePcd(self, ToPcd, FromPcd, Module=""):
947 #
948 # in case there's PCDs coming from FDF file, which have no type given.
949 # at this point, ToPcd.Type has the type found from dependent
950 # package
951 #
952 if FromPcd != None:
953 if ToPcd.Pending and FromPcd.Type not in [None, '']:
954 ToPcd.Type = FromPcd.Type
955 elif ToPcd.Type not in [None, ''] and FromPcd.Type not in [None, ''] \
956 and ToPcd.Type != FromPcd.Type:
957 EdkLogger.error("build", OPTION_CONFLICT, "Mismatched PCD type",
958 ExtraData="%s.%s is defined as [%s] in module %s, but as [%s] in platform."\
959 % (ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName,
960 ToPcd.Type, Module, FromPcd.Type),
961 File=self.MetaFile)
962
963 if FromPcd.MaxDatumSize not in [None, '']:
964 ToPcd.MaxDatumSize = FromPcd.MaxDatumSize
965 if FromPcd.DefaultValue not in [None, '']:
966 ToPcd.DefaultValue = FromPcd.DefaultValue
967 if FromPcd.TokenValue not in [None, '']:
968 ToPcd.TokenValue = FromPcd.TokenValue
969 if FromPcd.MaxDatumSize not in [None, '']:
970 ToPcd.MaxDatumSize = FromPcd.MaxDatumSize
971 if FromPcd.DatumType not in [None, '']:
972 ToPcd.DatumType = FromPcd.DatumType
973 if FromPcd.SkuInfoList not in [None, '', []]:
974 ToPcd.SkuInfoList = FromPcd.SkuInfoList
975
976 # check the validation of datum
977 IsValid, Cause = CheckPcdDatum(ToPcd.DatumType, ToPcd.DefaultValue)
978 if not IsValid:
979 EdkLogger.error('build', FORMAT_INVALID, Cause, File=self.MetaFile,
980 ExtraData="%s.%s" % (ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName))
981
982 if ToPcd.DatumType == "VOID*" and ToPcd.MaxDatumSize in ['', None]:
983 EdkLogger.debug(EdkLogger.DEBUG_9, "No MaxDatumSize specified for PCD %s.%s" \
984 % (ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName))
985 Value = ToPcd.DefaultValue
986 if Value in [None, '']:
987 ToPcd.MaxDatumSize = 1
988 elif Value[0] == 'L':
989 ToPcd.MaxDatumSize = str(len(Value) * 2)
990 elif Value[0] == '{':
991 ToPcd.MaxDatumSize = str(len(Value.split(',')))
992 else:
993 ToPcd.MaxDatumSize = str(len(Value))
994
995 # apply default SKU for dynamic PCDS if specified one is not available
996 if (ToPcd.Type in PCD_DYNAMIC_TYPE_LIST or ToPcd.Type in PCD_DYNAMIC_EX_TYPE_LIST) \
997 and ToPcd.SkuInfoList in [None, {}, '']:
998 if self.Platform.SkuName in self.Platform.SkuIds:
999 SkuName = self.Platform.SkuName
1000 else:
1001 SkuName = 'DEFAULT'
1002 ToPcd.SkuInfoList = {
1003 SkuName : SkuInfoClass(SkuName, self.Platform.SkuIds[SkuName], '', '', '', '', '', ToPcd.DefaultValue)
1004 }
1005
1006 ## Apply PCD setting defined platform to a module
1007 #
1008 # @param Module The module from which the PCD setting will be overrided
1009 #
1010 # @retval PCD_list The list PCDs with settings from platform
1011 #
1012 def ApplyPcdSetting(self, Module, Pcds):
1013 # for each PCD in module
1014 for Name,Guid in Pcds:
1015 PcdInModule = Pcds[Name,Guid]
1016 # find out the PCD setting in platform
1017 if (Name,Guid) in self.Platform.Pcds:
1018 PcdInPlatform = self.Platform.Pcds[Name,Guid]
1019 else:
1020 PcdInPlatform = None
1021 # then override the settings if any
1022 self._OverridePcd(PcdInModule, PcdInPlatform, Module)
1023 # resolve the VariableGuid value
1024 for SkuId in PcdInModule.SkuInfoList:
1025 Sku = PcdInModule.SkuInfoList[SkuId]
1026 if Sku.VariableGuid == '': continue
1027 Sku.VariableGuidValue = GuidValue(Sku.VariableGuid, self.PackageList)
1028 if Sku.VariableGuidValue == None:
1029 PackageList = "\n\t".join([str(P) for P in self.PackageList])
1030 EdkLogger.error(
1031 'build',
1032 RESOURCE_NOT_AVAILABLE,
1033 "Value of GUID [%s] is not found in" % Sku.VariableGuid,
1034 ExtraData=PackageList + "\n\t(used with %s.%s from module %s)" \
1035 % (Guid, Name, str(Module)),
1036 File=self.MetaFile
1037 )
1038
1039 # override PCD settings with module specific setting
1040 if Module in self.Platform.Modules:
1041 PlatformModule = self.Platform.Modules[str(Module)]
1042 for Key in PlatformModule.Pcds:
1043 if Key in Pcds:
1044 self._OverridePcd(Pcds[Key], PlatformModule.Pcds[Key], Module)
1045 return Pcds.values()
1046
1047 ## Resolve library names to library modules
1048 #
1049 # (for R8.x modules)
1050 #
1051 # @param Module The module from which the library names will be resolved
1052 #
1053 # @retval library_list The list of library modules
1054 #
1055 def ResolveLibraryReference(self, Module):
1056 EdkLogger.verbose("")
1057 EdkLogger.verbose("Library instances of module [%s] [%s]:" % (str(Module), self.Arch))
1058 LibraryConsumerList = [Module]
1059
1060 # "CompilerStub" is a must for R8 modules
1061 if Module.Libraries:
1062 Module.Libraries.append("CompilerStub")
1063 LibraryList = []
1064 while len(LibraryConsumerList) > 0:
1065 M = LibraryConsumerList.pop()
1066 for LibraryName in M.Libraries:
1067 Library = self.Platform.LibraryClasses[LibraryName, ':dummy:']
1068 if Library == None:
1069 for Key in self.Platform.LibraryClasses.data.keys():
1070 if LibraryName.upper() == Key.upper():
1071 Library = self.Platform.LibraryClasses[Key, ':dummy:']
1072 break
1073 if Library == None:
1074 EdkLogger.warn("build", "Library [%s] is not found" % LibraryName, File=str(M),
1075 ExtraData="\t%s [%s]" % (str(Module), self.Arch))
1076 continue
1077
1078 if Library not in LibraryList:
1079 LibraryList.append(Library)
1080 LibraryConsumerList.append(Library)
1081 EdkLogger.verbose("\t" + LibraryName + " : " + str(Library) + ' ' + str(type(Library)))
1082 return LibraryList
1083
1084 ## Expand * in build option key
1085 #
1086 # @param Options Options to be expanded
1087 #
1088 # @retval options Options expanded
1089 #
1090 def _ExpandBuildOption(self, Options, ModuleStyle=None):
1091 BuildOptions = {}
1092 FamilyMatch = False
1093 FamilyIsNull = True
1094 for Key in Options:
1095 if ModuleStyle != None and len (Key) > 2:
1096 # Check Module style is EDK or EDKII.
1097 # Only append build option for the matched style module.
1098 if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:
1099 continue
1100 elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:
1101 continue
1102 Family = Key[0]
1103 Target, Tag, Arch, Tool, Attr = Key[1].split("_")
1104 # if tool chain family doesn't match, skip it
1105 if Tool in self.ToolDefinition and Family != "":
1106 FamilyIsNull = False
1107 if self.ToolDefinition[Tool].get(TAB_TOD_DEFINES_BUILDRULEFAMILY, "") != "":
1108 if Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_BUILDRULEFAMILY]:
1109 continue
1110 elif Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_FAMILY]:
1111 continue
1112 FamilyMatch = True
1113 # expand any wildcard
1114 if Target == "*" or Target == self.BuildTarget:
1115 if Tag == "*" or Tag == self.ToolChain:
1116 if Arch == "*" or Arch == self.Arch:
1117 if Tool not in BuildOptions:
1118 BuildOptions[Tool] = {}
1119 if Attr != "FLAGS" or Attr not in BuildOptions[Tool]:
1120 BuildOptions[Tool][Attr] = Options[Key]
1121 else:
1122 # append options for the same tool
1123 BuildOptions[Tool][Attr] += " " + Options[Key]
1124 # Build Option Family has been checked, which need't to be checked again for family.
1125 if FamilyMatch or FamilyIsNull:
1126 return BuildOptions
1127
1128 for Key in Options:
1129 if ModuleStyle != None and len (Key) > 2:
1130 # Check Module style is EDK or EDKII.
1131 # Only append build option for the matched style module.
1132 if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:
1133 continue
1134 elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:
1135 continue
1136 Family = Key[0]
1137 Target, Tag, Arch, Tool, Attr = Key[1].split("_")
1138 # if tool chain family doesn't match, skip it
1139 if Tool not in self.ToolDefinition or Family =="":
1140 continue
1141 # option has been added before
1142 if Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_FAMILY]:
1143 continue
1144
1145 # expand any wildcard
1146 if Target == "*" or Target == self.BuildTarget:
1147 if Tag == "*" or Tag == self.ToolChain:
1148 if Arch == "*" or Arch == self.Arch:
1149 if Tool not in BuildOptions:
1150 BuildOptions[Tool] = {}
1151 if Attr != "FLAGS" or Attr not in BuildOptions[Tool]:
1152 BuildOptions[Tool][Attr] = Options[Key]
1153 else:
1154 # append options for the same tool
1155 BuildOptions[Tool][Attr] += " " + Options[Key]
1156 return BuildOptions
1157
1158 ## Append build options in platform to a module
1159 #
1160 # @param Module The module to which the build options will be appened
1161 #
1162 # @retval options The options appended with build options in platform
1163 #
1164 def ApplyBuildOption(self, Module):
1165 # Get the different options for the different style module
1166 if Module.AutoGenVersion < 0x00010005:
1167 PlatformOptions = self.EdkBuildOption
1168 else:
1169 PlatformOptions = self.EdkIIBuildOption
1170 ModuleOptions = self._ExpandBuildOption(Module.BuildOptions)
1171 if Module in self.Platform.Modules:
1172 PlatformModule = self.Platform.Modules[str(Module)]
1173 PlatformModuleOptions = self._ExpandBuildOption(PlatformModule.BuildOptions)
1174 else:
1175 PlatformModuleOptions = {}
1176
1177 AllTools = set(ModuleOptions.keys() + PlatformOptions.keys() + PlatformModuleOptions.keys() + self.ToolDefinition.keys())
1178 BuildOptions = {}
1179 for Tool in AllTools:
1180 if Tool not in BuildOptions:
1181 BuildOptions[Tool] = {}
1182
1183 for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, PlatformModuleOptions]:
1184 if Tool not in Options:
1185 continue
1186 for Attr in Options[Tool]:
1187 Value = Options[Tool][Attr]
1188 if Attr not in BuildOptions[Tool]:
1189 BuildOptions[Tool][Attr] = ""
1190 # check if override is indicated
1191 if Value.startswith('='):
1192 BuildOptions[Tool][Attr] = Value[1:]
1193 else:
1194 BuildOptions[Tool][Attr] += " " + Value
1195 if Module.AutoGenVersion < 0x00010005 and self.Workspace.UniFlag != None:
1196 #
1197 # Override UNI flag only for EDK module.
1198 #
1199 if 'BUILD' not in BuildOptions:
1200 BuildOptions['BUILD'] = {}
1201 BuildOptions['BUILD']['FLAGS'] = self.Workspace.UniFlag
1202 return BuildOptions
1203
1204 Platform = property(_GetPlatform)
1205 Name = property(_GetName)
1206 Guid = property(_GetGuid)
1207 Version = property(_GetVersion)
1208
1209 OutputDir = property(_GetOutputDir)
1210 BuildDir = property(_GetBuildDir)
1211 MakeFileDir = property(_GetMakeFileDir)
1212 FdfFile = property(_GetFdfFile)
1213
1214 PcdTokenNumber = property(_GetPcdTokenNumbers) # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
1215 DynamicPcdList = property(_GetDynamicPcdList) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1216 NonDynamicPcdList = property(_GetNonDynamicPcdList) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1217 PackageList = property(_GetPackageList)
1218
1219 ToolDefinition = property(_GetToolDefinition) # toolcode : tool path
1220 ToolDefinitionFile = property(_GetToolDefFile) # toolcode : lib path
1221 ToolChainFamily = property(_GetToolChainFamily)
1222 BuildRuleFamily = property(_GetBuildRuleFamily)
1223 BuildOption = property(_GetBuildOptions) # toolcode : option
1224 EdkBuildOption = property(_GetEdkBuildOptions) # edktoolcode : option
1225 EdkIIBuildOption = property(_GetEdkIIBuildOptions) # edkiitoolcode : option
1226
1227 BuildCommand = property(_GetBuildCommand)
1228 BuildRule = property(_GetBuildRule)
1229 ModuleAutoGenList = property(_GetModuleAutoGenList)
1230 LibraryAutoGenList = property(_GetLibraryAutoGenList)
1231
1232 ## ModuleAutoGen class
1233 #
1234 # This class encapsules the AutoGen behaviors for the build tools. In addition to
1235 # the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according
1236 # to the [depex] section in module's inf file.
1237 #
1238 class ModuleAutoGen(AutoGen):
1239 ## The real constructor of ModuleAutoGen
1240 #
1241 # This method is not supposed to be called by users of ModuleAutoGen. It's
1242 # only used by factory method __new__() to do real initialization work for an
1243 # object of ModuleAutoGen
1244 #
1245 # @param Workspace EdkIIWorkspaceBuild object
1246 # @param ModuleFile The path of module file
1247 # @param Target Build target (DEBUG, RELEASE)
1248 # @param Toolchain Name of tool chain
1249 # @param Arch The arch the module supports
1250 # @param PlatformFile Platform meta-file
1251 #
1252 def _Init(self, Workspace, ModuleFile, Target, Toolchain, Arch, PlatformFile):
1253 EdkLogger.debug(EdkLogger.DEBUG_9, "AutoGen module [%s] [%s]" % (ModuleFile, Arch))
1254 GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (ModuleFile, Arch, Toolchain, Target)
1255
1256 self.Workspace = Workspace
1257 self.WorkspaceDir = Workspace.WorkspaceDir
1258
1259 self.MetaFile = ModuleFile
1260 self.PlatformInfo = PlatformAutoGen(Workspace, PlatformFile, Target, Toolchain, Arch)
1261 # check if this module is employed by active platform
1262 if not self.PlatformInfo.ValidModule(self.MetaFile):
1263 EdkLogger.verbose("Module [%s] for [%s] is not employed by active platform\n" \
1264 % (self.MetaFile, Arch))
1265 return False
1266
1267 self.SourceDir = self.MetaFile.SubDir
1268 self.SourceOverrideDir = None
1269 # use overrided path defined in DSC file
1270 if self.MetaFile.Key in GlobalData.gOverrideDir:
1271 self.SourceOverrideDir = GlobalData.gOverrideDir[self.MetaFile.Key]
1272
1273 self.ToolChain = Toolchain
1274 self.BuildTarget = Target
1275 self.Arch = Arch
1276 self.ToolChainFamily = self.PlatformInfo.ToolChainFamily
1277 self.BuildRuleFamily = self.PlatformInfo.BuildRuleFamily
1278
1279 self.IsMakeFileCreated = False
1280 self.IsCodeFileCreated = False
1281
1282 self.BuildDatabase = self.Workspace.BuildDatabase
1283
1284 self._Module = None
1285 self._Name = None
1286 self._Guid = None
1287 self._Version = None
1288 self._ModuleType = None
1289 self._ComponentType = None
1290 self._PcdIsDriver = None
1291 self._AutoGenVersion = None
1292 self._LibraryFlag = None
1293 self._CustomMakefile = None
1294 self._Macro = None
1295
1296 self._BuildDir = None
1297 self._OutputDir = None
1298 self._DebugDir = None
1299 self._MakeFileDir = None
1300
1301 self._IncludePathList = None
1302 self._AutoGenFileList = None
1303 self._UnicodeFileList = None
1304 self._SourceFileList = None
1305 self._ObjectFileList = None
1306 self._BinaryFileList = None
1307
1308 self._DependentPackageList = None
1309 self._DependentLibraryList = None
1310 self._LibraryAutoGenList = None
1311 self._DerivedPackageList = None
1312 self._ModulePcdList = None
1313 self._LibraryPcdList = None
1314 self._GuidList = None
1315 self._ProtocolList = None
1316 self._PpiList = None
1317 self._DepexList = None
1318 self._DepexExpressionList = None
1319 self._BuildOption = None
1320 self._BuildTargets = None
1321 self._IntroBuildTargetList = None
1322 self._FinalBuildTargetList = None
1323 self._FileTypes = None
1324 self._BuildRules = None
1325
1326 return True
1327
1328 def __repr__(self):
1329 return "%s [%s]" % (self.MetaFile, self.Arch)
1330
1331 # Macros could be used in build_rule.txt (also Makefile)
1332 def _GetMacros(self):
1333 if self._Macro == None:
1334 self._Macro = sdict()
1335 self._Macro["WORKSPACE" ] = self.WorkspaceDir
1336 self._Macro["MODULE_NAME" ] = self.Name
1337 self._Macro["MODULE_GUID" ] = self.Guid
1338 self._Macro["MODULE_VERSION" ] = self.Version
1339 self._Macro["MODULE_TYPE" ] = self.ModuleType
1340 self._Macro["MODULE_FILE" ] = str(self.MetaFile)
1341 self._Macro["MODULE_FILE_BASE_NAME" ] = self.MetaFile.BaseName
1342 self._Macro["MODULE_RELATIVE_DIR" ] = self.SourceDir
1343 self._Macro["MODULE_DIR" ] = self.SourceDir
1344
1345 self._Macro["BASE_NAME" ] = self.Name
1346
1347 self._Macro["ARCH" ] = self.Arch
1348 self._Macro["TOOLCHAIN" ] = self.ToolChain
1349 self._Macro["TOOLCHAIN_TAG" ] = self.ToolChain
1350 self._Macro["TARGET" ] = self.BuildTarget
1351
1352 self._Macro["BUILD_DIR" ] = self.PlatformInfo.BuildDir
1353 self._Macro["BIN_DIR" ] = os.path.join(self.PlatformInfo.BuildDir, self.Arch)
1354 self._Macro["LIB_DIR" ] = os.path.join(self.PlatformInfo.BuildDir, self.Arch)
1355 self._Macro["MODULE_BUILD_DIR" ] = self.BuildDir
1356 self._Macro["OUTPUT_DIR" ] = self.OutputDir
1357 self._Macro["DEBUG_DIR" ] = self.DebugDir
1358 return self._Macro
1359
1360 ## Return the module build data object
1361 def _GetModule(self):
1362 if self._Module == None:
1363 self._Module = self.Workspace.BuildDatabase[self.MetaFile, self.Arch]
1364 return self._Module
1365
1366 ## Return the module name
1367 def _GetBaseName(self):
1368 return self.Module.BaseName
1369
1370 ## Return the module SourceOverridePath
1371 def _GetSourceOverridePath(self):
1372 return self.Module.SourceOverridePath
1373
1374 ## Return the module meta-file GUID
1375 def _GetGuid(self):
1376 return self.Module.Guid
1377
1378 ## Return the module version
1379 def _GetVersion(self):
1380 return self.Module.Version
1381
1382 ## Return the module type
1383 def _GetModuleType(self):
1384 return self.Module.ModuleType
1385
1386 ## Return the component type (for R8.x style of module)
1387 def _GetComponentType(self):
1388 return self.Module.ComponentType
1389
1390 ## Return the build type
1391 def _GetBuildType(self):
1392 return self.Module.BuildType
1393
1394 ## Return the PCD_IS_DRIVER setting
1395 def _GetPcdIsDriver(self):
1396 return self.Module.PcdIsDriver
1397
1398 ## Return the autogen version, i.e. module meta-file version
1399 def _GetAutoGenVersion(self):
1400 return self.Module.AutoGenVersion
1401
1402 ## Check if the module is library or not
1403 def _IsLibrary(self):
1404 if self._LibraryFlag == None:
1405 if self.Module.LibraryClass != None and self.Module.LibraryClass != []:
1406 self._LibraryFlag = True
1407 else:
1408 self._LibraryFlag = False
1409 return self._LibraryFlag
1410
1411 ## Return the directory to store intermediate files of the module
1412 def _GetBuildDir(self):
1413 if self._BuildDir == None:
1414 self._BuildDir = path.join(
1415 self.PlatformInfo.BuildDir,
1416 self.Arch,
1417 self.SourceDir,
1418 self.MetaFile.BaseName
1419 )
1420 CreateDirectory(self._BuildDir)
1421 return self._BuildDir
1422
1423 ## Return the directory to store the intermediate object files of the mdoule
1424 def _GetOutputDir(self):
1425 if self._OutputDir == None:
1426 self._OutputDir = path.join(self.BuildDir, "OUTPUT")
1427 CreateDirectory(self._OutputDir)
1428 return self._OutputDir
1429
1430 ## Return the directory to store auto-gened source files of the mdoule
1431 def _GetDebugDir(self):
1432 if self._DebugDir == None:
1433 self._DebugDir = path.join(self.BuildDir, "DEBUG")
1434 CreateDirectory(self._DebugDir)
1435 return self._DebugDir
1436
1437 ## Return the path of custom file
1438 def _GetCustomMakefile(self):
1439 if self._CustomMakefile == None:
1440 self._CustomMakefile = {}
1441 for Type in self.Module.CustomMakefile:
1442 if Type in gMakeTypeMap:
1443 MakeType = gMakeTypeMap[Type]
1444 else:
1445 MakeType = 'nmake'
1446 if self.SourceOverrideDir != None:
1447 File = os.path.join(self.SourceOverrideDir, self.Module.CustomMakefile[Type])
1448 if not os.path.exists(File):
1449 File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])
1450 else:
1451 File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])
1452 self._CustomMakefile[MakeType] = File
1453 return self._CustomMakefile
1454
1455 ## Return the directory of the makefile
1456 #
1457 # @retval string The directory string of module's makefile
1458 #
1459 def _GetMakeFileDir(self):
1460 return self.BuildDir
1461
1462 ## Return build command string
1463 #
1464 # @retval string Build command string
1465 #
1466 def _GetBuildCommand(self):
1467 return self.PlatformInfo.BuildCommand
1468
1469 ## Get object list of all packages the module and its dependent libraries belong to
1470 #
1471 # @retval list The list of package object
1472 #
1473 def _GetDerivedPackageList(self):
1474 PackageList = []
1475 for M in [self.Module] + self.DependentLibraryList:
1476 for Package in M.Packages:
1477 if Package in PackageList:
1478 continue
1479 PackageList.append(Package)
1480 return PackageList
1481
1482 ## Merge dependency expression
1483 #
1484 # @retval list The token list of the dependency expression after parsed
1485 #
1486 def _GetDepexTokenList(self):
1487 if self._DepexList == None:
1488 self._DepexList = {}
1489 if self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:
1490 return self._DepexList
1491
1492 self._DepexList[self.ModuleType] = []
1493
1494 for ModuleType in self._DepexList:
1495 DepexList = self._DepexList[ModuleType]
1496 #
1497 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
1498 #
1499 for M in [self.Module] + self.DependentLibraryList:
1500 Inherited = False
1501 for D in M.Depex[self.Arch, ModuleType]:
1502 if DepexList != []:
1503 DepexList.append('AND')
1504 DepexList.append('(')
1505 DepexList.extend(D)
1506 if DepexList[-1] == 'END': # no need of a END at this time
1507 DepexList.pop()
1508 DepexList.append(')')
1509 Inherited = True
1510 if Inherited:
1511 EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexList))
1512 if 'BEFORE' in DepexList or 'AFTER' in DepexList:
1513 break
1514 if len(DepexList) > 0:
1515 EdkLogger.verbose('')
1516 return self._DepexList
1517
1518 ## Merge dependency expression
1519 #
1520 # @retval list The token list of the dependency expression after parsed
1521 #
1522 def _GetDepexExpressionTokenList(self):
1523 if self._DepexExpressionList == None:
1524 self._DepexExpressionList = {}
1525 if self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:
1526 return self._DepexExpressionList
1527
1528 self._DepexExpressionList[self.ModuleType] = ''
1529
1530 for ModuleType in self._DepexExpressionList:
1531 DepexExpressionList = self._DepexExpressionList[ModuleType]
1532 #
1533 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
1534 #
1535 for M in [self.Module] + self.DependentLibraryList:
1536 Inherited = False
1537 for D in M.DepexExpression[self.Arch, ModuleType]:
1538 if DepexExpressionList != '':
1539 DepexExpressionList += ' AND '
1540 DepexExpressionList += '('
1541 DepexExpressionList += D
1542 DepexExpressionList = DepexExpressionList.rstrip('END').strip()
1543 DepexExpressionList += ')'
1544 Inherited = True
1545 if Inherited:
1546 EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexExpressionList))
1547 if 'BEFORE' in DepexExpressionList or 'AFTER' in DepexExpressionList:
1548 break
1549 if len(DepexExpressionList) > 0:
1550 EdkLogger.verbose('')
1551 self._DepexExpressionList[ModuleType] = DepexExpressionList
1552 return self._DepexExpressionList
1553
1554 ## Return the list of specification version required for the module
1555 #
1556 # @retval list The list of specification defined in module file
1557 #
1558 def _GetSpecification(self):
1559 return self.Module.Specification
1560
1561 ## Tool option for the module build
1562 #
1563 # @param PlatformInfo The object of PlatformBuildInfo
1564 # @retval dict The dict containing valid options
1565 #
1566 def _GetModuleBuildOption(self):
1567 if self._BuildOption == None:
1568 self._BuildOption = self.PlatformInfo.ApplyBuildOption(self.Module)
1569 return self._BuildOption
1570
1571 ## Return a list of files which can be built from source
1572 #
1573 # What kind of files can be built is determined by build rules in
1574 # $(WORKSPACE)/Conf/build_rule.txt and toolchain family.
1575 #
1576 def _GetSourceFileList(self):
1577 if self._SourceFileList == None:
1578 self._SourceFileList = []
1579 for F in self.Module.Sources:
1580 # match tool chain
1581 if F.TagName != "" and F.TagName != self.ToolChain:
1582 EdkLogger.debug(EdkLogger.DEBUG_9, "The toolchain [%s] for processing file [%s] is found, "
1583 "but [%s] is needed" % (F.TagName, str(F), self.ToolChain))
1584 continue
1585 # match tool chain family
1586 if F.ToolChainFamily != "" and F.ToolChainFamily != self.ToolChainFamily:
1587 EdkLogger.debug(
1588 EdkLogger.DEBUG_0,
1589 "The file [%s] must be built by tools of [%s], " \
1590 "but current toolchain family is [%s]" \
1591 % (str(F), F.ToolChainFamily, self.ToolChainFamily))
1592 continue
1593
1594 # add the file path into search path list for file including
1595 if F.Dir not in self.IncludePathList and self.AutoGenVersion >= 0x00010005:
1596 self.IncludePathList.insert(0, F.Dir)
1597 self._SourceFileList.append(F)
1598 self._ApplyBuildRule(F, TAB_UNKNOWN_FILE)
1599 return self._SourceFileList
1600
1601 ## Return the list of unicode files
1602 def _GetUnicodeFileList(self):
1603 if self._UnicodeFileList == None:
1604 if TAB_UNICODE_FILE in self.FileTypes:
1605 self._UnicodeFileList = self.FileTypes[TAB_UNICODE_FILE]
1606 else:
1607 self._UnicodeFileList = []
1608 return self._UnicodeFileList
1609
1610 ## Return a list of files which can be built from binary
1611 #
1612 # "Build" binary files are just to copy them to build directory.
1613 #
1614 # @retval list The list of files which can be built later
1615 #
1616 def _GetBinaryFiles(self):
1617 if self._BinaryFileList == None:
1618 self._BinaryFileList = []
1619 for F in self.Module.Binaries:
1620 if F.Target not in ['COMMON', '*'] and F.Target != self.BuildTarget:
1621 continue
1622 self._BinaryFileList.append(F)
1623 self._ApplyBuildRule(F, F.Type)
1624 return self._BinaryFileList
1625
1626 def _GetBuildRules(self):
1627 if self._BuildRules == None:
1628 BuildRules = {}
1629 BuildRuleDatabase = self.PlatformInfo.BuildRule
1630 for Type in BuildRuleDatabase.FileTypeList:
1631 #first try getting build rule by BuildRuleFamily
1632 RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.BuildRuleFamily]
1633 if not RuleObject:
1634 # build type is always module type, but ...
1635 if self.ModuleType != self.BuildType:
1636 RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.BuildRuleFamily]
1637 #second try getting build rule by ToolChainFamily
1638 if not RuleObject:
1639 RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.ToolChainFamily]
1640 if not RuleObject:
1641 # build type is always module type, but ...
1642 if self.ModuleType != self.BuildType:
1643 RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.ToolChainFamily]
1644 if not RuleObject:
1645 continue
1646 RuleObject = RuleObject.Instantiate(self.Macros)
1647 BuildRules[Type] = RuleObject
1648 for Ext in RuleObject.SourceFileExtList:
1649 BuildRules[Ext] = RuleObject
1650 self._BuildRules = BuildRules
1651 return self._BuildRules
1652
1653 def _ApplyBuildRule(self, File, FileType):
1654 if self._BuildTargets == None:
1655 self._IntroBuildTargetList = set()
1656 self._FinalBuildTargetList = set()
1657 self._BuildTargets = {}
1658 self._FileTypes = {}
1659
1660 LastTarget = None
1661 RuleChain = []
1662 SourceList = [File]
1663 Index = 0
1664 while Index < len(SourceList):
1665 Source = SourceList[Index]
1666 Index = Index + 1
1667
1668 if Source != File:
1669 CreateDirectory(Source.Dir)
1670
1671 if File.IsBinary and File == Source and self._BinaryFileList != None and File in self._BinaryFileList:
1672 RuleObject = self.BuildRules[TAB_DEFAULT_BINARY_FILE]
1673 elif FileType in self.BuildRules:
1674 RuleObject = self.BuildRules[FileType]
1675 elif Source.Ext in self.BuildRules:
1676 RuleObject = self.BuildRules[Source.Ext]
1677 else:
1678 # stop at no more rules
1679 if LastTarget:
1680 self._FinalBuildTargetList.add(LastTarget)
1681 break
1682
1683 FileType = RuleObject.SourceFileType
1684 if FileType not in self._FileTypes:
1685 self._FileTypes[FileType] = set()
1686 self._FileTypes[FileType].add(Source)
1687
1688 # stop at STATIC_LIBRARY for library
1689 if self.IsLibrary and FileType == TAB_STATIC_LIBRARY:
1690 if LastTarget:
1691 self._FinalBuildTargetList.add(LastTarget)
1692 break
1693
1694 Target = RuleObject.Apply(Source)
1695 if not Target:
1696 if LastTarget:
1697 self._FinalBuildTargetList.add(LastTarget)
1698 break
1699 elif not Target.Outputs:
1700 # Only do build for target with outputs
1701 self._FinalBuildTargetList.add(Target)
1702
1703 if FileType not in self._BuildTargets:
1704 self._BuildTargets[FileType] = set()
1705 self._BuildTargets[FileType].add(Target)
1706
1707 if not Source.IsBinary and Source == File:
1708 self._IntroBuildTargetList.add(Target)
1709
1710 # to avoid cyclic rule
1711 if FileType in RuleChain:
1712 break
1713
1714 RuleChain.append(FileType)
1715 SourceList.extend(Target.Outputs)
1716 LastTarget = Target
1717 FileType = TAB_UNKNOWN_FILE
1718
1719 def _GetTargets(self):
1720 if self._BuildTargets == None:
1721 self._IntroBuildTargetList = set()
1722 self._FinalBuildTargetList = set()
1723 self._BuildTargets = {}
1724 self._FileTypes = {}
1725
1726 #TRICK: call _GetSourceFileList to apply build rule for binary files
1727 if self.SourceFileList:
1728 pass
1729
1730 #TRICK: call _GetBinaryFileList to apply build rule for binary files
1731 if self.BinaryFileList:
1732 pass
1733
1734 return self._BuildTargets
1735
1736 def _GetIntroTargetList(self):
1737 self._GetTargets()
1738 return self._IntroBuildTargetList
1739
1740 def _GetFinalTargetList(self):
1741 self._GetTargets()
1742 return self._FinalBuildTargetList
1743
1744 def _GetFileTypes(self):
1745 self._GetTargets()
1746 return self._FileTypes
1747
1748 ## Get the list of package object the module depends on
1749 #
1750 # @retval list The package object list
1751 #
1752 def _GetDependentPackageList(self):
1753 return self.Module.Packages
1754
1755 ## Return the list of auto-generated code file
1756 #
1757 # @retval list The list of auto-generated file
1758 #
1759 def _GetAutoGenFileList(self):
1760 UniStringAutoGenC = True
1761 UniStringBinBuffer = None
1762 if self.BuildType == 'UEFI_HII':
1763 UniStringBinBuffer = StringIO()
1764 UniStringAutoGenC = False
1765 if self._AutoGenFileList == None:
1766 self._AutoGenFileList = {}
1767 AutoGenC = TemplateString()
1768 AutoGenH = TemplateString()
1769 StringH = TemplateString()
1770 GenC.CreateCode(self, AutoGenC, AutoGenH, StringH, UniStringAutoGenC, UniStringBinBuffer)
1771 if str(AutoGenC) != "" and TAB_C_CODE_FILE in self.FileTypes:
1772 AutoFile = PathClass(gAutoGenCodeFileName, self.DebugDir)
1773 self._AutoGenFileList[AutoFile] = str(AutoGenC)
1774 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
1775 if str(AutoGenH) != "":
1776 AutoFile = PathClass(gAutoGenHeaderFileName, self.DebugDir)
1777 self._AutoGenFileList[AutoFile] = str(AutoGenH)
1778 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
1779 if str(StringH) != "":
1780 AutoFile = PathClass(gAutoGenStringFileName % {"module_name":self.Name}, self.DebugDir)
1781 self._AutoGenFileList[AutoFile] = str(StringH)
1782 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
1783 if UniStringBinBuffer != None and UniStringBinBuffer.getvalue() != "":
1784 AutoFile = PathClass(gAutoGenStringFormFileName % {"module_name":self.Name}, self.OutputDir)
1785 self._AutoGenFileList[AutoFile] = UniStringBinBuffer.getvalue()
1786 AutoFile.IsBinary = True
1787 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
1788 if UniStringBinBuffer != None:
1789 UniStringBinBuffer.close()
1790 return self._AutoGenFileList
1791
1792 ## Return the list of library modules explicitly or implicityly used by this module
1793 def _GetLibraryList(self):
1794 if self._DependentLibraryList == None:
1795 # only merge library classes and PCD for non-library module
1796 if self.IsLibrary:
1797 self._DependentLibraryList = []
1798 else:
1799 if self.AutoGenVersion < 0x00010005:
1800 self._DependentLibraryList = self.PlatformInfo.ResolveLibraryReference(self.Module)
1801 else:
1802 self._DependentLibraryList = self.PlatformInfo.ApplyLibraryInstance(self.Module)
1803 return self._DependentLibraryList
1804
1805 ## Get the list of PCDs from current module
1806 #
1807 # @retval list The list of PCD
1808 #
1809 def _GetModulePcdList(self):
1810 if self._ModulePcdList == None:
1811 # apply PCD settings from platform
1812 self._ModulePcdList = self.PlatformInfo.ApplyPcdSetting(self.Module, self.Module.Pcds)
1813 return self._ModulePcdList
1814
1815 ## Get the list of PCDs from dependent libraries
1816 #
1817 # @retval list The list of PCD
1818 #
1819 def _GetLibraryPcdList(self):
1820 if self._LibraryPcdList == None:
1821 Pcds = {}
1822 if not self.IsLibrary:
1823 # get PCDs from dependent libraries
1824 for Library in self.DependentLibraryList:
1825 for Key in Library.Pcds:
1826 # skip duplicated PCDs
1827 if Key in self.Module.Pcds or Key in Pcds:
1828 continue
1829 Pcds[Key] = copy.copy(Library.Pcds[Key])
1830 # apply PCD settings from platform
1831 self._LibraryPcdList = self.PlatformInfo.ApplyPcdSetting(self.Module, Pcds)
1832 else:
1833 self._LibraryPcdList = []
1834 return self._LibraryPcdList
1835
1836 ## Get the GUID value mapping
1837 #
1838 # @retval dict The mapping between GUID cname and its value
1839 #
1840 def _GetGuidList(self):
1841 if self._GuidList == None:
1842 self._GuidList = self.Module.Guids
1843 for Library in self.DependentLibraryList:
1844 self._GuidList.update(Library.Guids)
1845 return self._GuidList
1846
1847 ## Get the protocol value mapping
1848 #
1849 # @retval dict The mapping between protocol cname and its value
1850 #
1851 def _GetProtocolList(self):
1852 if self._ProtocolList == None:
1853 self._ProtocolList = self.Module.Protocols
1854 for Library in self.DependentLibraryList:
1855 self._ProtocolList.update(Library.Protocols)
1856 return self._ProtocolList
1857
1858 ## Get the PPI value mapping
1859 #
1860 # @retval dict The mapping between PPI cname and its value
1861 #
1862 def _GetPpiList(self):
1863 if self._PpiList == None:
1864 self._PpiList = self.Module.Ppis
1865 for Library in self.DependentLibraryList:
1866 self._PpiList.update(Library.Ppis)
1867 return self._PpiList
1868
1869 ## Get the list of include search path
1870 #
1871 # @retval list The list path
1872 #
1873 def _GetIncludePathList(self):
1874 if self._IncludePathList == None:
1875 self._IncludePathList = []
1876 if self.AutoGenVersion < 0x00010005:
1877 for Inc in self.Module.Includes:
1878 if Inc not in self._IncludePathList:
1879 self._IncludePathList.append(Inc)
1880 # for r8 modules
1881 Inc = path.join(Inc, self.Arch.capitalize())
1882 if os.path.exists(Inc) and Inc not in self._IncludePathList:
1883 self._IncludePathList.append(Inc)
1884 # r8 module needs to put DEBUG_DIR at the end of search path and not to use SOURCE_DIR all the time
1885 self._IncludePathList.append(self.DebugDir)
1886 else:
1887 self._IncludePathList.append(self.MetaFile.Dir)
1888 self._IncludePathList.append(self.DebugDir)
1889
1890 for Package in self.Module.Packages:
1891 PackageDir = path.join(self.WorkspaceDir, Package.MetaFile.Dir)
1892 if PackageDir not in self._IncludePathList:
1893 self._IncludePathList.append(PackageDir)
1894 for Inc in Package.Includes:
1895 if Inc not in self._IncludePathList:
1896 self._IncludePathList.append(str(Inc))
1897 return self._IncludePathList
1898
1899 ## Create makefile for the module and its dependent libraries
1900 #
1901 # @param CreateLibraryMakeFile Flag indicating if or not the makefiles of
1902 # dependent libraries will be created
1903 #
1904 def CreateMakeFile(self, CreateLibraryMakeFile=True):
1905 if self.IsMakeFileCreated:
1906 return
1907
1908 if not self.IsLibrary and CreateLibraryMakeFile:
1909 for LibraryAutoGen in self.LibraryAutoGenList:
1910 LibraryAutoGen.CreateMakeFile()
1911
1912 if len(self.CustomMakefile) == 0:
1913 Makefile = GenMake.ModuleMakefile(self)
1914 else:
1915 Makefile = GenMake.CustomMakefile(self)
1916 if Makefile.Generate():
1917 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated makefile for module %s [%s]" %
1918 (self.Name, self.Arch))
1919 else:
1920 EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of makefile for module %s [%s]" %
1921 (self.Name, self.Arch))
1922
1923 self.IsMakeFileCreated = True
1924
1925 ## Create autogen code for the module and its dependent libraries
1926 #
1927 # @param CreateLibraryCodeFile Flag indicating if or not the code of
1928 # dependent libraries will be created
1929 #
1930 def CreateCodeFile(self, CreateLibraryCodeFile=True):
1931 if self.IsCodeFileCreated:
1932 return
1933
1934 if not self.IsLibrary and CreateLibraryCodeFile:
1935 for LibraryAutoGen in self.LibraryAutoGenList:
1936 LibraryAutoGen.CreateCodeFile()
1937
1938 AutoGenList = []
1939 IgoredAutoGenList = []
1940
1941 for File in self.AutoGenFileList:
1942 if GenC.Generate(File.Path, self.AutoGenFileList[File], File.IsBinary):
1943 #Ignore R8 AutoGen.c
1944 if self.AutoGenVersion < 0x00010005 and File.Name == 'AutoGen.c':
1945 continue
1946
1947 AutoGenList.append(str(File))
1948 else:
1949 IgoredAutoGenList.append(str(File))
1950
1951 # Skip the following code for EDK I inf
1952 if self.AutoGenVersion < 0x00010005:
1953 return
1954
1955 for ModuleType in self.DepexList:
1956 if len(self.DepexList[ModuleType]) == 0:
1957 continue
1958 Dpx = GenDepex.DependencyExpression(self.DepexList[ModuleType], ModuleType, True)
1959 DpxFile = gAutoGenDepexFileName % {"module_name" : self.Name}
1960
1961 if Dpx.Generate(path.join(self.OutputDir, DpxFile)):
1962 AutoGenList.append(str(DpxFile))
1963 else:
1964 IgoredAutoGenList.append(str(DpxFile))
1965
1966 if IgoredAutoGenList == []:
1967 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated [%s] files for module %s [%s]" %
1968 (" ".join(AutoGenList), self.Name, self.Arch))
1969 elif AutoGenList == []:
1970 EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of [%s] files for module %s [%s]" %
1971 (" ".join(IgoredAutoGenList), self.Name, self.Arch))
1972 else:
1973 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated [%s] (skipped %s) files for module %s [%s]" %
1974 (" ".join(AutoGenList), " ".join(IgoredAutoGenList), self.Name, self.Arch))
1975
1976 self.IsCodeFileCreated = True
1977 return AutoGenList
1978
1979 ## Summarize the ModuleAutoGen objects of all libraries used by this module
1980 def _GetLibraryAutoGenList(self):
1981 if self._LibraryAutoGenList == None:
1982 self._LibraryAutoGenList = []
1983 for Library in self.DependentLibraryList:
1984 La = ModuleAutoGen(
1985 self.Workspace,
1986 Library.MetaFile,
1987 self.BuildTarget,
1988 self.ToolChain,
1989 self.Arch,
1990 self.PlatformInfo.MetaFile
1991 )
1992 if La not in self._LibraryAutoGenList:
1993 self._LibraryAutoGenList.append(La)
1994 for Lib in La.CodaTargetList:
1995 self._ApplyBuildRule(Lib.Target, TAB_UNKNOWN_FILE)
1996 return self._LibraryAutoGenList
1997
1998 ## Return build command string
1999 #
2000 # @retval string Build command string
2001 #
2002 def _GetBuildCommand(self):
2003 return self.PlatformInfo.BuildCommand
2004
2005
2006 Module = property(_GetModule)
2007 Name = property(_GetBaseName)
2008 Guid = property(_GetGuid)
2009 Version = property(_GetVersion)
2010 ModuleType = property(_GetModuleType)
2011 ComponentType = property(_GetComponentType)
2012 BuildType = property(_GetBuildType)
2013 PcdIsDriver = property(_GetPcdIsDriver)
2014 AutoGenVersion = property(_GetAutoGenVersion)
2015 Macros = property(_GetMacros)
2016 Specification = property(_GetSpecification)
2017
2018 IsLibrary = property(_IsLibrary)
2019
2020 BuildDir = property(_GetBuildDir)
2021 OutputDir = property(_GetOutputDir)
2022 DebugDir = property(_GetDebugDir)
2023 MakeFileDir = property(_GetMakeFileDir)
2024 CustomMakefile = property(_GetCustomMakefile)
2025
2026 IncludePathList = property(_GetIncludePathList)
2027 AutoGenFileList = property(_GetAutoGenFileList)
2028 UnicodeFileList = property(_GetUnicodeFileList)
2029 SourceFileList = property(_GetSourceFileList)
2030 BinaryFileList = property(_GetBinaryFiles) # FileType : [File List]
2031 Targets = property(_GetTargets)
2032 IntroTargetList = property(_GetIntroTargetList)
2033 CodaTargetList = property(_GetFinalTargetList)
2034 FileTypes = property(_GetFileTypes)
2035 BuildRules = property(_GetBuildRules)
2036
2037 DependentPackageList = property(_GetDependentPackageList)
2038 DependentLibraryList = property(_GetLibraryList)
2039 LibraryAutoGenList = property(_GetLibraryAutoGenList)
2040 DerivedPackageList = property(_GetDerivedPackageList)
2041
2042 ModulePcdList = property(_GetModulePcdList)
2043 LibraryPcdList = property(_GetLibraryPcdList)
2044 GuidList = property(_GetGuidList)
2045 ProtocolList = property(_GetProtocolList)
2046 PpiList = property(_GetPpiList)
2047 DepexList = property(_GetDepexTokenList)
2048 DepexExpressionList = property(_GetDepexExpressionTokenList)
2049 BuildOption = property(_GetModuleBuildOption)
2050 BuildCommand = property(_GetBuildCommand)
2051
2052 # This acts like the main() function for the script, unless it is 'import'ed into another script.
2053 if __name__ == '__main__':
2054 pass
2055