2 # Generate AutoGen.h, AutoGen.c and *.depex files
\r
4 # Copyright (c) 2007, Intel Corporation
\r
5 # All rights reserved. This program and the accompanying materials
\r
6 # are licensed and made available under the terms and conditions of the BSD License
\r
7 # which accompanies this distribution. The full text of the license may be found at
\r
8 # http://opensource.org/licenses/bsd-license.php
\r
10 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
\r
11 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
\r
19 import os.path as path
\r
21 from optparse import OptionParser
\r
22 from optparse import make_option
\r
24 import Common.EdkLogger
\r
29 from BuildInfo import *
\r
30 from StrGather import *
\r
31 from BuildEngine import *
\r
33 from Common.BuildToolError import *
\r
34 from Common.EdkIIWorkspaceBuild import *
\r
35 from Common.EdkIIWorkspace import *
\r
36 from Common.DataType import *
\r
37 from Common.Misc import *
\r
38 from Common.String import *
\r
40 ## Regular expression for splitting Dependency Expression stirng into tokens
\r
41 gDepexTokenPattern = re.compile("(\(|\)|\w+| \S+\.inf)")
\r
43 ## Mapping Makefile type
\r
44 gMakeTypeMap = {"MSFT":"nmake", "GCC":"gmake"}
\r
46 ## Default output flag for all tools
\r
47 gDefaultOutputFlag = "-o "
\r
49 ## Output flags for specific tools
\r
51 ("MSFT", "CC", "OUTPUT") : "/Fo",
\r
52 ("MSFT", "SLINK", "OUTPUT") : "/OUT:",
\r
53 ("MSFT", "DLINK", "OUTPUT") : "/OUT:",
\r
54 ("MSFT", "ASMLINK", "OUTPUT") : "/OUT:",
\r
55 ("MSFT", "PCH", "OUTPUT") : "/Fp",
\r
56 ("MSFT", "ASM", "OUTPUT") : "/Fo",
\r
58 ("INTEL", "CC", "OUTPUT") : "/Fo",
\r
59 ("INTEL", "SLINK", "OUTPUT") : "/OUT:",
\r
60 ("INTEL", "DLINK", "OUTPUT") : "/OUT:",
\r
61 ("INTEL", "ASMLINK", "OUTPUT") : "/OUT:",
\r
62 ("INTEL", "PCH", "OUTPUT") : "/Fp",
\r
63 ("INTEL", "ASM", "OUTPUT") : "/Fo",
\r
65 ("GCC", "CC", "OUTPUT") : "-o ",
\r
66 ("GCC", "SLINK", "OUTPUT") : "-cr ",
\r
67 ("GCC", "DLINK", "OUTPUT") : "-o ",
\r
68 ("GCC", "ASMLINK", "OUTPUT") : "-o ",
\r
69 ("GCC", "PCH", "OUTPUT") : "-o ",
\r
70 ("GCC", "ASM", "OUTPUT") : "-o ",
\r
73 ## Flag for include file search path
\r
74 gIncludeFlag = {"MSFT" : "/I", "GCC" : "-I", "INTEL" : "-I"}
\r
76 ## Build rule configuration file
\r
77 gBuildRuleFile = 'Conf/build_rule.txt'
\r
79 ## default file name for AutoGen
\r
80 gAutoGenCodeFileName = "AutoGen.c"
\r
81 gAutoGenHeaderFileName = "AutoGen.h"
\r
82 gAutoGenDepexFileName = "%(module_name)s.depex"
\r
84 ## AutoGen class for platform
\r
86 # PlatformAutoGen class will re-organize the original information in platform
\r
87 # file in order to generate makefile for platform.
\r
89 class PlatformAutoGen:
\r
90 # database to maintain the objects of PlatformAutoGen
\r
91 _Database = {} # (platform file, BuildTarget, ToolChain) : PlatformAutoGen object
\r
93 ## The real constructor of PlatformAutoGen
\r
95 # This method is not supposed to be called by users of PlatformAutoGen. It's
\r
96 # only used by factory method New() to do real initialization work for an
\r
97 # object of PlatformAutoGen
\r
99 # @param Workspace EdkIIWorkspaceBuild object
\r
100 # @param PlatformFile Platform file (DSC file)
\r
101 # @param Target Build target (DEBUG, RELEASE)
\r
102 # @param Toolchain Name of tool chain
\r
103 # @param ArchList List of arch the platform supports
\r
105 def _Init(self, Workspace, PlatformFile, Target, Toolchain, ArchList):
\r
106 self.PlatformFile = str(PlatformFile)
\r
107 self.Workspace = Workspace
\r
108 self.WorkspaceDir = Workspace.WorkspaceDir
\r
109 self.ToolChain = Toolchain
\r
110 self.BuildTarget = Target
\r
111 self.ArchList = ArchList
\r
113 EdkLogger.verbose("\nAutoGen platform [%s] [%s]" % (self.PlatformFile, " ".join(self.ArchList)))
\r
115 # get the original module/package/platform objects
\r
116 self.ModuleDatabase = {}
\r
117 for a in Workspace.Build:
\r
118 self.ModuleDatabase[a] = Workspace.Build[a].ModuleDatabase
\r
120 self.PackageDatabase = {}
\r
121 for a in Workspace.Build:
\r
122 self.PackageDatabase[a] = Workspace.Build[a].PackageDatabase
\r
124 self.PlatformDatabase = {}
\r
125 for a in Workspace.Build:
\r
126 self.PlatformDatabase[a] = Workspace.Build[a].PlatformDatabase
\r
128 # flag indicating if the makefile/C-code file has been created or not
\r
129 self.IsMakeFileCreated = False
\r
130 self.IsCodeFileCreated = False
\r
133 # collect build information for the platform
\r
135 self.BuildInfo = {} # arch : PlatformBuildInfo Object
\r
138 for Arch in self.ArchList:
\r
139 if Arch not in self.PlatformDatabase or self.PlatformFile not in self.PlatformDatabase[Arch]:
\r
140 EdkLogger.error("AutoGen", AUTOGEN_ERROR,
\r
141 "[%s] is not the active platform, or [%s] is not supported by the active platform!"
\r
142 % (PlatformFile, Arch))
\r
143 Platform = self.PlatformDatabase[Arch][PlatformFile]
\r
144 self.Platform[Arch] = Platform
\r
145 self.BuildInfo[Arch] = self.CollectBuildInfo(Platform, Arch)
\r
149 # The file path of platform file will be used to represent hash value of this object
\r
151 # @retval int Hash value of the file path of platform file
\r
153 def __hash__(self):
\r
154 return hash(self.PlatformFile)
\r
158 # The file path of platform file will be used to represent this object
\r
160 # @retval string String of platform file path
\r
163 return self.PlatformFile
\r
165 ## Factory method to create a PlatformAutoGen object
\r
167 # This method will check if an object of PlatformAutoGen has been created
\r
168 # for given platform. And if true, just return it. Otherwise it will create
\r
169 # a new PlatformAutoGen. That means there will be only one PlatformAutoGen
\r
170 # object for the same platform.
\r
172 # @param Workspace EdkIIWorkspaceBuild object
\r
173 # @param Platform Platform file (DSC file)
\r
174 # @param Target Build target (DEBUG, RELEASE)
\r
175 # @param Toolchain Name of tool chain
\r
176 # @param ArchList List of arch the platform supports
\r
177 # @param ModuleAutoGenFlag Flag indicating if creating ModuleAutoGen
\r
178 # objects for mdoules in the platform or not
\r
180 # @retval PlatformAutoGen object
\r
183 def New(Workspace, Platform, Target, Toolchain, ArchList, ModuleAutoGenFlag=False):
\r
184 # check if the object for the platform has been created
\r
185 Key = (Platform, Target, Toolchain)
\r
186 if Key not in PlatformAutoGen._Database:
\r
187 if ArchList == None or ArchList == []:
\r
189 AutoGenObject = PlatformAutoGen()
\r
190 AutoGenObject._Init(Workspace, Platform, Target, Toolchain, ArchList)
\r
191 PlatformAutoGen._Database[Key] = AutoGenObject
\r
193 AutoGenObject = PlatformAutoGen._Database[Key]
\r
195 # create ModuleAutoGen objects for modules in the platform
\r
196 if ModuleAutoGenFlag:
\r
197 AutoGenObject.CreateModuleAutoGen()
\r
199 return AutoGenObject
\r
201 ## Collect build information for the platform
\r
203 # Collect build information, such as FDF file path, dynamic pcd list,
\r
204 # package list, tool chain configuration, build rules, etc.
\r
206 # @param Platform Platform file (DSC file)
\r
207 # @param Arch One of arch the platform supports
\r
209 # @retval PlatformBuildInfo object
\r
211 def CollectBuildInfo(self, Platform, Arch):
\r
212 Info = PlatformBuildInfo(Platform)
\r
215 Info.ToolChain = self.ToolChain
\r
216 Info.BuildTarget = self.BuildTarget
\r
218 Info.WorkspaceDir = self.WorkspaceDir
\r
219 Info.SourceDir = path.dirname(Platform.DescFilePath)
\r
220 Info.OutputDir = Platform.OutputDirectory
\r
221 if os.path.isabs(Info.OutputDir):
\r
222 Info.BuildDir = path.join(path.abspath(Info.OutputDir), self.BuildTarget + "_" + self.ToolChain)
\r
224 Info.BuildDir = path.join(Info.WorkspaceDir, Info.OutputDir, self.BuildTarget + "_" + self.ToolChain)
\r
225 Info.MakeFileDir = Info.BuildDir
\r
226 if self.Workspace.Fdf != "":
\r
227 Info.FdfFile= path.join(self.WorkspaceDir, self.Workspace.Fdf)
\r
229 Info.NonDynamicPcdList, Info.DynamicPcdList = self.GetPcdList(Platform, Arch)
\r
230 Info.PcdTokenNumber = self.GeneratePcdTokenNumber(Platform, Info.NonDynamicPcdList, Info.DynamicPcdList)
\r
231 Info.PackageList = self.PackageDatabase[Arch].values()
\r
233 self.GetToolDefinition(Info)
\r
234 Info.BuildRule = self.GetBuildRule()
\r
235 Info.FdTargetList = self.Workspace.FdTargetList
\r
236 Info.FvTargetList = self.Workspace.FvTargetList
\r
240 ## Return directory of platform makefile
\r
242 # @retval string Makefile directory
\r
244 def GetMakeFileDir(self):
\r
245 return self.BuildInfo[self.ArchList[0]].MakeFileDir
\r
247 ## Return build command string
\r
249 # @retval string Build command string
\r
251 def GetBuildCommand(self, Arch=None):
\r
255 Arch = self.ArchList
\r
258 if A in self.BuildInfo and "MAKE" in self.BuildInfo[A].ToolPath:
\r
259 Command += (self.BuildInfo[A].ToolPath["MAKE"],)
\r
260 if "MAKE" in self.BuildInfo[A].ToolOption:
\r
261 NewOption = self.BuildInfo[A].ToolOption["MAKE"].strip()
\r
262 if NewOption != '':
\r
263 Command += (NewOption,)
\r
265 if len(Command) == 0:
\r
266 EdkLogger.error("AutoGen", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!")
\r
269 ## Parse build_rule.txt in $(WORKSPACE)/Conf/build_rule.txt
\r
271 # @retval BuildRule object
\r
273 def GetBuildRule(self):
\r
274 BuildRuleFile = self.Workspace.TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_BUILD_RULE_CONF]
\r
275 if BuildRuleFile in [None, '']:
\r
276 BuildRuleFile = gBuildRuleFile
\r
277 return BuildRule(self.Workspace.WorkspaceFile(BuildRuleFile))
\r
279 ## Get tool chain definition
\r
281 # Get each tool defition for given tool chain from tools_def.txt and platform
\r
283 # @param Info PlatformBuildInfo object to store the definition
\r
285 def GetToolDefinition(self, Info):
\r
286 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDictionary
\r
287 ToolCodeList = self.Workspace.ToolDef.ToolsDefTxtDatabase["COMMAND_TYPE"]
\r
288 for Tool in ToolCodeList:
\r
289 KeyBaseString = "%s_%s_%s_%s" % (Info.BuildTarget, Info.ToolChain, Info.Arch, Tool)
\r
291 Key = "%s_PATH" % KeyBaseString
\r
292 if Key not in ToolDefinition:
\r
294 Path = ToolDefinition[Key]
\r
296 Key = "%s_FAMILY" % KeyBaseString
\r
297 if Key in ToolDefinition:
\r
298 Family = ToolDefinition[Key]
\r
302 Key = "%s_FLAGS" % KeyBaseString
\r
303 if Key in ToolDefinition:
\r
304 Option = ToolDefinition[Key]
\r
308 Key = "%s_DLL" % KeyBaseString
\r
309 if Key in ToolDefinition:
\r
310 Dll = ToolDefinition[Key]
\r
311 # set the DLL path in system's PATH environment
\r
312 os.environ["PATH"] = Dll + os.pathsep + os.environ["PATH"]
\r
316 Key = KeyBaseString + "_OUTPUT"
\r
317 if Key in ToolDefinition:
\r
318 OutputFlag = ToolDefinition[Key]
\r
319 elif (Family, Tool, "OUTPUT") in gOutputFlag:
\r
320 OutputFlag = gOutputFlag[Family, Tool, "OUTPUT"]
\r
321 if OutputFlag[0] == '"' and OutputFlag[-1] == '"':
\r
322 OutputFlag = OutputFlag[1:-1]
\r
324 OutputFlag = gDefaultOutputFlag
\r
326 InputFlag = gIncludeFlag[Family]
\r
328 Info.ToolPath[Tool] = Path
\r
329 Info.ToolDllPath[Tool] = Dll
\r
330 Info.ToolChainFamily[Tool] = Family
\r
331 Info.ToolOption[Tool] = Option
\r
332 Info.OutputFlag[Tool] = OutputFlag
\r
333 Info.IncludeFlag[Tool] = InputFlag
\r
335 # get tool options from platform
\r
336 BuildOptions = Info.Platform.BuildOptions
\r
337 for Key in BuildOptions:
\r
339 Target, Tag, Arch, Tool, Attr = Key[1].split("_")
\r
340 if Tool not in Info.ToolPath:
\r
342 if Family != None and Family != "" and Family != Info.ToolChainFamily[Tool]:
\r
344 if Target == "*" or Target == Info.BuildTarget:
\r
345 if Tag == "*" or Tag == Info.ToolChain:
\r
346 if Arch == "*" or Arch == Info.Arch:
\r
347 Info.BuildOption[Tool] = BuildOptions[Key]
\r
348 for Tool in Info.ToolOption:
\r
349 if Tool not in Info.BuildOption:
\r
350 Info.BuildOption[Tool] = ""
\r
352 ## Collect dynamic PCDs
\r
354 # Gather dynamic PCDs list from each module and their settings from platform
\r
356 # @param Platform The object of the platform
\r
357 # @param Arch One of the arch the platform supports
\r
359 # @retval lsit The list of dynamic PCD
\r
361 def GetPcdList(self, Platform, Arch):
\r
362 NonDynamicPcdList = []
\r
363 DynamicPcdList = []
\r
365 # for gathering error information
\r
366 NotFoundPcdList = set()
\r
367 NoDatumTypePcdList = set()
\r
369 for F in Platform.Modules:
\r
370 M = self.ModuleDatabase[Arch][F]
\r
372 PcdFromModule = M.Pcds[Key]
\r
373 # check if the setting of the PCD is found in platform
\r
374 if not PcdFromModule.IsOverrided:
\r
375 NotFoundPcdList.add("%s [%s]" % (" | ".join(Key), F))
\r
378 # make sure that the "VOID*" kind of datum has MaxDatumSize set
\r
379 if PcdFromModule.DatumType == "VOID*" and PcdFromModule.MaxDatumSize == None:
\r
380 NoDatumTypePcdList.add("%s [%s]" % (" | ".join(Key), F))
\r
382 if PcdFromModule.Type in GenC.gDynamicPcd or PcdFromModule.Type in GenC.gDynamicExPcd:
\r
383 # for autogen code purpose
\r
384 if M.ModuleType in ["PEIM", "PEI_CORE"]:
\r
385 PcdFromModule.Phase = "PEI"
\r
386 if PcdFromModule not in DynamicPcdList:
\r
387 DynamicPcdList.append(PcdFromModule)
\r
388 elif PcdFromModule not in NonDynamicPcdList:
\r
389 NonDynamicPcdList.append(PcdFromModule)
\r
391 # print out error information and break the build, if error found
\r
392 if len(NotFoundPcdList) > 0 or len(NoDatumTypePcdList) > 0:
\r
393 NotFoundPcdListString = "\n\t\t".join(NotFoundPcdList)
\r
394 NoDatumTypePcdListString = "\n\t\t".join(NoDatumTypePcdList)
\r
395 EdkLogger.error("AutoGen", AUTOGEN_ERROR, "PCD setting error",
\r
396 ExtraData="\n\tPCD(s) not found in platform:\n\t\t%s"
\r
397 "\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"
\r
398 % (NotFoundPcdListString, NoDatumTypePcdListString))
\r
399 return NonDynamicPcdList, DynamicPcdList
\r
401 ## Generate Token Number for all PCD
\r
403 # @param Platform The object of the platform
\r
404 # @param DynamicPcdList The list of all dynamic PCDs
\r
406 # @retval dict A dict object containing the PCD and its token number
\r
408 def GeneratePcdTokenNumber(self, Platform, NonDynamicPcdList, DynamicPcdList):
\r
409 PcdTokenNumber = sdict()
\r
411 for Pcd in DynamicPcdList:
\r
412 if Pcd.Phase == "PEI":
\r
413 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
\r
414 PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
\r
417 for Pcd in DynamicPcdList:
\r
418 if Pcd.Phase == "DXE":
\r
419 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
\r
420 PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
\r
423 for Pcd in NonDynamicPcdList:
\r
424 PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
\r
426 return PcdTokenNumber
\r
428 ## Create autogen object for each module in platform
\r
430 def CreateModuleAutoGen(self):
\r
431 for Arch in self.BuildInfo:
\r
432 Info = self.BuildInfo[Arch]
\r
433 for ModuleFile in Info.Platform.LibraryInstances:
\r
434 ModuleAutoGen.New(self.Workspace, Info.Platform, ModuleFile,
\r
435 Info.BuildTarget, Info.ToolChain, Info.Arch)
\r
437 for ModuleFile in Info.Platform.Modules:
\r
438 ModuleAutoGen.New(self.Workspace, Info.Platform, ModuleFile,
\r
439 Info.BuildTarget, Info.ToolChain, Info.Arch)
\r
441 ## Create makefile for the platform and mdoules in it
\r
443 # @param CreateLibraryCodeFile Flag indicating if the makefile for
\r
444 # modules will be created as well
\r
446 def CreateMakeFile(self, CreateModuleMakeFile=False):
\r
447 if CreateModuleMakeFile:
\r
448 for Arch in self.BuildInfo:
\r
449 Info = self.BuildInfo[Arch]
\r
450 for ModuleFile in Info.Platform.LibraryInstances:
\r
451 AutoGenObject = ModuleAutoGen.New(self.Workspace, Info.Platform, ModuleFile,
\r
452 Info.BuildTarget, Info.ToolChain, Info.Arch)
\r
453 AutoGenObject.CreateMakeFile(False)
\r
455 for ModuleFile in Info.Platform.Modules:
\r
456 AutoGenObject = ModuleAutoGen.New(self.Workspace, Info.Platform, ModuleFile,
\r
457 Info.BuildTarget, Info.ToolChain, Info.Arch)
\r
458 AutoGenObject.CreateMakeFile(False)
\r
460 # no need to create makefile for the platform more than once
\r
461 if self.IsMakeFileCreated:
\r
464 # create makefile for platform
\r
465 Makefile = GenMake.Makefile(self.BuildInfo)
\r
466 if Makefile.Generate():
\r
467 EdkLogger.verbose("Generated makefile for platform [%s] [%s]\n" %
\r
468 (self.PlatformFile, " ".join(self.ArchList)))
\r
470 EdkLogger.verbose("Skipped the generation of makefile for platform [%s] [%s]\n" %
\r
471 (self.PlatformFile, " ".join(self.ArchList)))
\r
472 self.IsMakeFileCreated = True
\r
474 ## Create autogen code for platform and modules
\r
476 # Since there's no autogen code for platform, this method will do nothing
\r
477 # if CreateModuleCodeFile is set to False.
\r
479 # @param CreateModuleCodeFile Flag indicating if creating module's
\r
480 # autogen code file or not
\r
482 def CreateCodeFile(self, CreateModuleCodeFile=False):
\r
483 # only module has code to be greated, so do nothing if CreateModuleCodeFile is False
\r
484 if self.IsCodeFileCreated or not CreateModuleCodeFile:
\r
487 for Arch in self.BuildInfo:
\r
488 Info = self.BuildInfo[Arch]
\r
489 for ModuleFile in Info.Platform.LibraryInstances:
\r
490 AutoGenObject = ModuleAutoGen.New(self.Workspace, Info.Platform, ModuleFile,
\r
491 Info.BuildTarget, Info.ToolChain, Info.Arch)
\r
492 AutoGenObject.CreateCodeFile()
\r
494 for ModuleFile in Info.Platform.Modules:
\r
495 AutoGenObject = ModuleAutoGen.New(self.Workspace, Info.Platform, ModuleFile,
\r
496 Info.BuildTarget, Info.ToolChain, Info.Arch)
\r
497 AutoGenObject.CreateCodeFile()
\r
498 # don't do this twice
\r
499 self.IsCodeFileCreated = True
\r
501 ## Test if a module is supported by the platform
\r
503 # An error will be raised directly if the module or its arch is not supported
\r
504 # by the platform or current configuration
\r
506 # @param Module The module file
\r
507 # @param Arch The arch the module will be built for
\r
509 def IsValidModule(self, Module, Arch):
\r
510 if Arch not in self.Workspace.SupArchList:
\r
512 #EdkLogger.error("AutoGen", AUTOGEN_ERROR, "[%s] is not supported by active platform [%s] [%s]!"
\r
513 # % (Arch, self.PlatformFile, self.Workspace.SupArchList))
\r
514 if Arch not in self.ArchList:
\r
516 #EdkLogger.error("AutoGen", AUTOGEN_ERROR, "[%s] is not supported by current build configuration!" % Arch)
\r
518 if Arch not in self.ModuleDatabase or str(Module) not in self.ModuleDatabase[Arch]:
\r
519 for A in self.ModuleDatabase:
\r
520 if str(Module) in self.ModuleDatabase[A]:
\r
523 EdkLogger.error("AutoGen", AUTOGEN_ERROR, "Module is not in active platform!",
\r
528 ## Find the package containing the module
\r
530 # Find out the package which contains the given module, according to the path
\r
531 # of the module and the package.
\r
533 # @param Module The module to be found for
\r
535 # @retval package Package object if found
\r
536 # @retval None None if not found
\r
538 def GetModuleOwnerPackage(self, Module):
\r
539 for Arch in self.PackageDatabase:
\r
540 Pdb = self.PackageDatabase[Arch]
\r
541 for PackagePath in Pdb:
\r
542 PackageDir = path.dirname(PackagePath)
\r
544 # if package's path is the first part of module's path, bingo!
\r
546 if str(Module).find(PackageDir) == 0:
\r
547 return Pdb[PackagePath]
\r
551 ## Get platform object
\r
553 # @param PlatformFile The file path of the platform
\r
554 # @param Arch One of the arch the platform supports
\r
556 # @retval object The object of the platform
\r
558 def GetPlatformObject(self, PlatformFile, Arch):
\r
559 if Arch not in self.PlatformDatabase or PlatformFile not in self.PlatformDatabase[Arch]:
\r
561 return self.PlatformDatabase[Arch][PlatformFile]
\r
563 ## Get package object
\r
565 # @param PackageFile The file path of the package
\r
566 # @param Arch One of the arch the package supports
\r
568 # @retval object The object of the package
\r
570 def GetPackageObject(self, PackageFile, Arch):
\r
571 if Arch not in self.PackageDatabase or PackageFile not in self.PackageDatabase[Arch]:
\r
573 return self.PackageDatabase[Arch][PackageFile]
\r
575 ## Get module object
\r
577 # @param ModuleFile The file path of the module
\r
578 # @param Arch One of the arch the module supports
\r
580 # @retval object The object of the module
\r
582 def GetModuleObject(self, ModuleFile, Arch):
\r
583 if Arch not in self.ModuleDatabase or ModuleFile not in self.ModuleDatabase[Arch]:
\r
585 return self.ModuleDatabase[Arch][ModuleFile]
\r
587 ## Add ModuleAutoGen object for a module in platform build information
\r
589 # @param ModuleAutoGen The ModuleAutoGen object for a module
\r
590 # @param Arch The arch of the module
\r
592 def AddModuleAutoGen(self, ModuleAutoGen, Arch):
\r
593 if ModuleAutoGen not in self.BuildInfo[Arch].ModuleAutoGenList:
\r
594 self.BuildInfo[Arch].ModuleAutoGenList.append(ModuleAutoGen)
\r
596 ## Add ModuleAutoGen object for a library in platform build information
\r
598 # @param LibraryAutoGen The ModuleAutoGen object for a library module
\r
599 # @param Arch The arch of the library
\r
601 def AddLibraryAutoGen(self, LibraryAutoGen, Arch):
\r
602 if LibraryAutoGen not in self.BuildInfo[Arch].LibraryAutoGenList:
\r
603 self.BuildInfo[Arch].LibraryAutoGenList.append(LibraryAutoGen)
\r
607 # This class encapsules the AutoGen behaviors for the build tools. In addition to
\r
608 # the generation of AutoGen.h and AutoGen.c, it can generate *.depex file according
\r
609 # to the [depex] section in module's inf file. The result of parsing unicode file
\r
610 # has been incorporated either.
\r
612 class ModuleAutoGen(object):
\r
613 # The cache for the objects of ModuleAutoGen
\r
615 # The cache for the object of PlatformAutoGen
\r
616 _PlatformAutoGen = None
\r
618 ## The real constructor of ModuleAutoGen
\r
620 # This method is not supposed to be called by users of ModuleAutoGen. It's
\r
621 # only used by factory method New() to do real initialization work for an
\r
622 # object of ModuleAutoGen
\r
624 # @param Workspace EdkIIWorkspaceBuild object
\r
625 # @param PlatformAutoGenObj Platform file (DSC file)
\r
626 # @param ModuleFile The path of module file
\r
627 # @param Target Build target (DEBUG, RELEASE)
\r
628 # @param Toolchain Name of tool chain
\r
629 # @param Arch The arch the module supports
\r
631 def _Init(self, Workspace, PlatformAutoGenObj, ModuleFile, Target, Toolchain, Arch):
\r
632 self.ModuleFile = str(ModuleFile)
\r
633 self.PlatformFile = PlatformAutoGenObj.PlatformFile
\r
635 self.Workspace = Workspace
\r
636 self.WorkspaceDir = Workspace.WorkspaceDir
\r
638 self.ToolChain = Toolchain
\r
639 self.ToolChainFamily = "MSFT"
\r
640 self.BuildTarget = Target
\r
643 self.IsMakeFileCreated = False
\r
644 self.IsCodeFileCreated = False
\r
646 self.PlatformAutoGen = PlatformAutoGenObj
\r
647 if not self.PlatformAutoGen.IsValidModule(ModuleFile, self.Arch):
\r
651 # autogen for module
\r
653 EdkLogger.verbose("\nAutoGen module [%s] [%s]" % (ModuleFile, self.Arch))
\r
655 self.Platform = self.PlatformAutoGen.GetPlatformObject(self.PlatformFile, self.Arch)
\r
656 self.Module = self.PlatformAutoGen.GetModuleObject(self.ModuleFile, self.Arch)
\r
658 self.Package = self.PlatformAutoGen.GetModuleOwnerPackage(self.Module)
\r
660 self.AutoGenC = TemplateString()
\r
661 self.AutoGenH = TemplateString()
\r
663 self.BuildInfo = self.GetModuleBuildInfo()
\r
668 # Use module file path and arch to do the comparison
\r
670 # @retval True if the file path and arch are equal
\r
671 # @retval False if the file path or arch are different
\r
673 def __eq__(self, Other):
\r
674 return Other != None and self.ModuleFile == Other.ModuleFile and self.Arch == Other.Arch
\r
678 # The file path and arch of the module will be used to represent hash value of this object
\r
680 # @retval int Hash value of the file path and arch name of the module
\r
682 def __hash__(self):
\r
683 return hash(self.ModuleFile) + hash(self.Arch)
\r
685 ## String representation of this object
\r
687 # @retval string The string of file path and arch
\r
690 return "%s [%s]" % (self.ModuleFile, self.Arch)
\r
692 ## Factory method to create a ModuleAutoGen object
\r
694 # This method will check if an object of ModuleAutoGen has been created
\r
695 # for given platform. And if true, just return it. Otherwise it will create
\r
696 # a new ModuleAutoGen. That means there will be only one ModuleAutoGen
\r
697 # object for the same platform.
\r
699 # @param Workspace EdkIIWorkspaceBuild object
\r
700 # @param Platform Platform file (DSC file)
\r
701 # @param Module Module file (INF file)
\r
702 # @param Target Build target (DEBUG, RELEASE)
\r
703 # @param Toolchain Name of tool chain
\r
704 # @param Arch The arch of the module
\r
706 # @retval ModuleAutoGen object
\r
709 def New(Workspace, Platform, Module, Target, Toolchain, Arch):
\r
710 # creating module autogen needs platform's autogen
\r
711 _PlatformAutoGen = PlatformAutoGen.New(Workspace, Platform, Target, Toolchain, None)
\r
712 if _PlatformAutoGen == None:
\r
713 EdkLogger.error("AutoGen", AUTOGEN_ERROR, "No platform AutoGen available!")
\r
715 # check if the autogen for the module has been created or not
\r
716 Key = (Module, Target, Toolchain, Arch)
\r
717 if Key not in ModuleAutoGen._Database:
\r
718 if Arch == None or Arch == "":
\r
720 AutoGenObject = ModuleAutoGen()
\r
721 if AutoGenObject._Init(Workspace, _PlatformAutoGen, Module, Target, Toolchain, Arch) == False:
\r
723 ModuleAutoGen._Database[Key] = AutoGenObject
\r
725 # for new ModuleAutoGen object, put it in platform's AutoGen
\r
726 if AutoGenObject.BuildInfo.IsLibrary:
\r
727 _PlatformAutoGen.AddLibraryAutoGen(AutoGenObject, Arch)
\r
729 _PlatformAutoGen.AddModuleAutoGen(AutoGenObject, Arch)
\r
730 return AutoGenObject
\r
732 return ModuleAutoGen._Database[Key]
\r
734 ## Gather module build information
\r
736 # @retval Info The object of ModuleBuildInfo
\r
738 def GetModuleBuildInfo(self):
\r
739 Info = ModuleBuildInfo(self.Module)
\r
740 self.BuildInfo = Info
\r
741 Info.PlatformInfo = self.PlatformAutoGen.BuildInfo[self.Arch]
\r
743 # basic information
\r
744 Info.WorkspaceDir = self.WorkspaceDir
\r
745 Info.BuildTarget = self.BuildTarget
\r
746 Info.ToolChain = self.ToolChain
\r
747 Info.Arch = self.Arch
\r
748 # Info.IsBinary = self.Module.BinaryModule
\r
749 Info.BaseName = self.Module.BaseName
\r
750 Info.FileBase, Info.FileExt = path.splitext(path.basename(self.Module.DescFilePath))
\r
751 Info.SourceDir = path.dirname(self.Module.DescFilePath)
\r
752 Info.BuildDir = os.path.join(Info.PlatformInfo.BuildDir,
\r
756 Info.OutputDir = os.path.join(Info.BuildDir, "OUTPUT")
\r
757 Info.DebugDir = os.path.join(Info.BuildDir, "DEBUG")
\r
758 Info.MakeFileDir = Info.BuildDir
\r
759 if not os.path.isabs(Info.BuildDir):
\r
760 os.chdir(Info.PlatformInfo.BuildDir)
\r
761 CreateDirectory(Info.OutputDir)
\r
762 CreateDirectory(Info.DebugDir)
\r
763 os.chdir(self.WorkspaceDir)
\r
765 for Type in self.Module.CustomMakefile:
\r
766 MakeType = gMakeTypeMap[Type]
\r
767 Info.CustomMakeFile[MakeType] = os.path.join(Info.SourceDir, self.Module.CustomMakefile[Type])
\r
769 if self.Module.LibraryClass != None and self.Module.LibraryClass != []:
\r
770 Info.IsLibrary = True
\r
771 Info.DependentLibraryList = []
\r
773 Info.IsLibrary = False
\r
774 Info.DependentLibraryList = self.GetSortedLibraryList()
\r
776 Info.DependentPackageList = self.GetDependentPackageList()
\r
777 Info.DerivedPackageList = self.GetDerivedPackageList()
\r
779 Info.BuildOption = self.GetModuleBuildOption(Info.PlatformInfo)
\r
780 if "DLINK" in Info.PlatformInfo.ToolStaticLib:
\r
781 Info.SystemLibraryList = Info.PlatformInfo.ToolStaticLib["DLINK"]
\r
783 Info.PcdIsDriver = self.Module.PcdIsDriver
\r
784 Info.PcdList = self.GetPcdList(Info.DependentLibraryList)
\r
785 Info.GuidList = self.GetGuidList()
\r
786 Info.ProtocolList = self.GetProtocolGuidList()
\r
787 Info.PpiList = self.GetPpiGuidList()
\r
788 Info.Macro = self.GetMacroList()
\r
789 Info.DepexList = self.GetDepexTokenList(Info)
\r
791 if Info.AutoGenVersion < 0x00010005:
\r
792 # r8 module needs to put DEBUG_DIR at the end search path and not to use SOURCE_DIR all the time
\r
793 Info.IncludePathList = self.GetIncludePathList(Info.DependentPackageList)
\r
794 Info.IncludePathList.append(Info.DebugDir)
\r
796 Info.IncludePathList = [os.path.join(Info.WorkspaceDir, Info.SourceDir), Info.DebugDir]
\r
797 Info.IncludePathList.extend(self.GetIncludePathList(Info.DependentPackageList))
\r
799 Info.SourceFileList = self.GetSourceFileList(Info)
\r
800 Info.AutoGenFileList = self.GetAutoGenFileList(Info)
\r
801 Info.BinaryFileDict = self.GetBinaryFiles()
\r
805 ## Return the directory of the makefile
\r
807 # @retval string The directory string of module's makefile
\r
809 def GetMakeFileDir(self):
\r
810 return self.BuildInfo.MakeFileDir
\r
812 ## Return build command string
\r
814 # @retval string Build command string
\r
816 def GetBuildCommand(self):
\r
817 return self.PlatformAutoGen.GetBuildCommand(self.Arch)
\r
819 ## Get object list of all packages the module and its dependent libraries belong to
\r
821 # @retval list The list of package object
\r
823 def GetDerivedPackageList(self):
\r
825 for M in [self.Module] + self.BuildInfo.DependentLibraryList:
\r
826 for Package in M.Packages:
\r
827 if Package not in PackageList:
\r
828 PackageList.append(self.PlatformAutoGen.GetPackageObject(Package, self.Arch))
\r
831 ## Parse dependency expression
\r
833 # @param Info The object of ModuleBuildInfo
\r
834 # @retval list The token list of the dependency expression after parsed
\r
836 def GetDepexTokenList(self, Info):
\r
837 Dxs = self.Module.Depex
\r
838 EdkLogger.verbose("DEPEX string = %s" % Dxs)
\r
840 # Append depex from dependent libraries
\r
842 for Lib in Info.DependentLibraryList:
\r
843 if Lib.Depex != None and Lib.Depex != "":
\r
844 if Dxs == None or Dxs == "":
\r
847 Dxs += " AND (" + Lib.Depex + ")"
\r
848 EdkLogger.verbose("DEPEX string (+%s) = %s" % (Lib.BaseName, Dxs))
\r
852 TokenList = gDepexTokenPattern.findall(Dxs)
\r
853 EdkLogger.debug(EdkLogger.DEBUG_8, "TokenList(raw) = %s" % (TokenList))
\r
854 for I in range(0, len(TokenList)):
\r
855 Token = TokenList[I].strip()
\r
856 if Token.endswith(".inf"): # module file name
\r
857 ModuleFile = os.path.normpath(Token)
\r
858 Token = gModuleDatabase[ModuleFile].Guid
\r
859 elif Token not in ['(', ')']+GenDepex.DependencyExpression.SupportedOpcode+\
\r
860 GenDepex.DependencyExpression.SupportedOperand: # GUID C Name
\r
862 for P in Info.DerivedPackageList:
\r
863 if GuidCName in P.Protocols:
\r
864 Token = P.Protocols[GuidCName]
\r
866 elif GuidCName in P.Ppis:
\r
867 Token = P.Ppis[GuidCName]
\r
869 elif GuidCName in P.Guids:
\r
870 Token = P.Guids[GuidCName]
\r
873 PackageListString = "\n\t".join([str(P) for P in self.BuildInfo.DerivedPackageList])
\r
874 EdkLogger.error("AutoGen", AUTOGEN_ERROR,
\r
875 "GUID [%s] used in module [%s] cannot be found in dependent packages!"
\r
876 % (GuidCName, self.Module),
\r
877 ExtraData=PackageListString)
\r
878 TokenList[I] = Token
\r
879 EdkLogger.debug(EdkLogger.DEBUG_8, "TokenList(guid) = %s" % " ".join(TokenList))
\r
882 ## Return the list of macro in module
\r
884 # @retval list The list of macro defined in module file
\r
886 def GetMacroList(self):
\r
887 # return ["%s %s" % (Name, self.Module.Specification[Name]) for Name in self.Module.Specification]
\r
888 return self.Module.Specification
\r
890 ## Tool option for the module build
\r
892 # @param PlatformInfo The object of PlatformBuildInfo
\r
893 # @retval dict The dict containing valid options
\r
895 def GetModuleBuildOption(self, PlatformInfo):
\r
896 BuildOption = self.Module.BuildOptions
\r
898 for Key in BuildOption:
\r
900 Target, Tag, Arch, Tool, Attr = Key[1].split("_")
\r
901 # if no tool defined for the option, skip it
\r
902 if Tool not in PlatformInfo.ToolPath:
\r
904 # if tool chain family doesn't match, skip it
\r
905 if Family != None and Family != "" and Family != PlatformInfo.ToolChainFamily[Tool]:
\r
907 # expand any wildcard
\r
908 if Target == "*" or Target == self.BuildTarget:
\r
909 if Tag == "*" or Tag == self.ToolChain:
\r
910 if Arch == "*" or Arch == self.Arch:
\r
911 if Tool not in OptionList:
\r
912 OptionList[Tool] = BuildOption[Key]
\r
914 # append options for the same tool
\r
915 OptionList[Tool] = OptionList[Tool] + " " + BuildOption[Key]
\r
916 # for those tools that have no option in module file, give it a empty string
\r
917 for Tool in PlatformInfo.ToolOption:
\r
918 if Tool not in OptionList:
\r
919 OptionList[Tool] = ""
\r
923 ## Return a list of files which can be built from source
\r
925 # What kind of files can be built is determined by build rules in
\r
926 # $(WORKSPACE)/Conf/build_rule.txt and toolchain family.
\r
928 # @param PlatformInfo The object of PlatformBuildInfo
\r
929 # @retval list The list of files which can be built later
\r
931 def GetSourceFileList(self, Info):
\r
932 # use toolchain family of CC as the primary toolchain family
\r
933 if "CC" not in Info.PlatformInfo.ToolChainFamily:
\r
934 EdkLogger.error("AutoGen", AUTOGEN_ERROR, "Tool [CC] is not supported for %s [%s, %s]" \
\r
935 % (Info.ToolChain, Info.BuildTarget, Info.Arch))
\r
936 ToolChainFamily = Info.PlatformInfo.ToolChainFamily["CC"]
\r
937 BuildRule = Info.PlatformInfo.BuildRule
\r
939 for F in self.Module.Sources:
\r
940 SourceFile = F.SourceFile
\r
942 if F.TagName != "" and F.TagName != self.ToolChain:
\r
943 EdkLogger.verbose("The toolchain [%s] for processing file [%s] is found, "
\r
944 "but [%s] is needed" % (F.TagName, F.SourceFile, self.ToolChain))
\r
946 # match tool chain family
\r
947 if F.ToolChainFamily != "" and F.ToolChainFamily != ToolChainFamily:
\r
948 EdkLogger.verbose("The file [%s] must be built by tools of [%s], "
\r
949 "but current toolchain family is [%s]" % (SourceFile, F.ToolChainFamily, ToolChainFamily))
\r
952 # add the file path into search path list for file including
\r
953 Dir = path.dirname(SourceFile)
\r
955 Dir = path.join(self.WorkspaceDir, self.BuildInfo.SourceDir, Dir)
\r
956 if Dir not in self.BuildInfo.IncludePathList:
\r
957 self.BuildInfo.IncludePathList.insert(0, Dir)
\r
959 # skip unknown file
\r
960 Base, Ext = path.splitext(SourceFile)
\r
962 # skip file which needs a tool having no matching toolchain family
\r
963 FileType, RuleObject = BuildRule.Get(Ext, ToolChainFamily)
\r
964 # unicode must be processed by AutoGen
\r
965 if FileType == "Unicode-Text-File":
\r
966 self.BuildInfo.UnicodeFileList.append(os.path.join(self.WorkspaceDir, self.BuildInfo.SourceDir, SourceFile))
\r
968 # if there's dxs file, don't use content in [depex] section to generate .depex file
\r
969 if FileType == "Dependency-Expression-File":
\r
970 Info.DepexList = []
\r
972 # no command, no build
\r
973 if RuleObject != None and RuleObject.CommandList == []:
\r
975 FileList.append([SourceFile, FileType, RuleObject])
\r
979 ## Return a list of files which can be built from binary
\r
981 # "Build" binary files are just to copy them to build directory.
\r
983 # @param PlatformInfo The object of PlatformBuildInfo
\r
984 # @retval list The list of files which can be built later
\r
986 def GetBinaryFiles(self):
\r
988 for F in self.Module.Binaries:
\r
989 if F.Target != '*' and F.Target != self.BuildTarget:
\r
991 if F.FileType not in FileDict:
\r
992 FileDict[F.FileType] = []
\r
993 FileDict[F.FileType].append(F.BinaryFile)
\r
996 ## Get the list of package object the module depends on
\r
998 # @retval list The package object list
\r
1000 def GetDependentPackageList(self):
\r
1002 for PackageFile in self.Module.Packages:
\r
1003 if PackageFile in PackageList:
\r
1005 Package = self.PlatformAutoGen.GetPackageObject(PackageFile, self.Arch)
\r
1006 if Package == None:
\r
1007 EdkLogger.error("AutoGen", FILE_NOT_FOUND, ExtraData=PackageFile)
\r
1008 PackageList.append(Package)
\r
1009 return PackageList
\r
1011 ## Return the list of auto-generated code file
\r
1013 # @param BuildInfo The object ModuleBuildInfo
\r
1014 # @retval list The list of auto-generated file
\r
1016 def GetAutoGenFileList(self, BuildInfo):
\r
1017 GenC.CreateCode(BuildInfo, self.AutoGenC, self.AutoGenH)
\r
1019 if self.AutoGenC.String != "":
\r
1020 FileList.append("AutoGen.c")
\r
1021 if self.AutoGenH.String != "":
\r
1022 FileList.append("AutoGen.h")
\r
1025 ## Get the list of library module object
\r
1027 # @retval list The list of library module list
\r
1029 def GetSortedLibraryList(self):
\r
1031 for Key in self.Module.LibraryClasses:
\r
1032 Library = self.PlatformAutoGen.GetModuleObject(self.Module.LibraryClasses[Key], self.Arch)
\r
1033 if Library not in LibraryList:
\r
1034 LibraryList.append(Library)
\r
1035 return LibraryList
\r
1037 ## Get the list of PCD
\r
1039 # @param DependentLibraryList The list of dependent library
\r
1040 # @retval list The list of PCD
\r
1042 def GetPcdList(self, DependentLibraryList):
\r
1044 for PcdKey in self.Module.Pcds:
\r
1045 PcdList.append(self.Module.Pcds[PcdKey])
\r
1048 ## Get the GUID value mapping
\r
1050 # @retval dict The mapping between GUID cname and its value
\r
1052 def GetGuidList(self):
\r
1055 for Key in self.Module.Guids:
\r
1056 for P in self.BuildInfo.DerivedPackageList:
\r
1057 if Key in P.Guids:
\r
1058 Guid[Key] = P.Guids[Key]
\r
1060 if Key in P.Protocols:
\r
1061 Guid[Key] = P.Protocols[Key]
\r
1064 Guid[Key] = P.Ppis[Key]
\r
1067 PackageListString = "\t" + "\n\t".join([str(P) for P in self.BuildInfo.DerivedPackageList])
\r
1068 EdkLogger.error("AutoGen", AUTOGEN_ERROR, 'GUID [%s] used by [%s] cannot be found in dependent packages' % (Key, self.Module),
\r
1069 ExtraData=PackageListString)
\r
1072 ## Get the protocol value mapping
\r
1074 # @retval dict The mapping between protocol cname and its value
\r
1076 def GetProtocolGuidList(self):
\r
1079 for Key in self.Module.Protocols:
\r
1080 for P in self.BuildInfo.DerivedPackageList:
\r
1081 if Key in P.Guids:
\r
1082 Guid[Key] = P.Guids[Key]
\r
1084 if Key in P.Protocols:
\r
1085 Guid[Key] = P.Protocols[Key]
\r
1088 Guid[Key] = P.Ppis[Key]
\r
1091 PackageListString = "\t" + "\n\t".join([str(P) for P in self.BuildInfo.DerivedPackageList])
\r
1092 EdkLogger.error("AutoGen", AUTOGEN_ERROR, 'Protocol [%s] used by [%s] cannot be found in dependent packages' % (Key, self.Module),
\r
1093 ExtraData=PackageListString)
\r
1096 ## Get the PPI value mapping
\r
1098 # @retval dict The mapping between PPI cname and its value
\r
1100 def GetPpiGuidList(self):
\r
1103 for Key in self.Module.Ppis:
\r
1104 for P in self.BuildInfo.DerivedPackageList:
\r
1105 if Key in P.Guids:
\r
1106 Guid[Key] = P.Guids[Key]
\r
1108 if Key in P.Protocols:
\r
1109 Guid[Key] = P.Protocols[Key]
\r
1112 Guid[Key] = P.Ppis[Key]
\r
1115 PackageListString = "\t" + "\n\t".join([str(P) for P in self.BuildInfo.DerivedPackageList])
\r
1116 EdkLogger.error("AutoGen", AUTOGEN_ERROR, 'PPI [%s] used by [%s] cannot be found in dependent packages' % (Key, self.Module),
\r
1117 ExtraData=PackageListString)
\r
1120 ## Get the list of include search path
\r
1122 # @param DependentPackageList The list of package object
\r
1123 # @retval list The list path
\r
1125 def GetIncludePathList(self, DependentPackageList):
\r
1126 IncludePathList = []
\r
1127 if self.BuildInfo.AutoGenVersion < 0x00010005:
\r
1128 for Inc in self.Module.Includes:
\r
1129 # '.' means "relative to module directory".
\r
1131 Inc = os.path.join(self.WorkspaceDir, self.BuildInfo.SourceDir, Inc)
\r
1133 Inc = os.path.join(self.WorkspaceDir, Inc)
\r
1134 IncludePathList.append(Inc)
\r
1136 IncludePathList.append(os.path.join(Inc, self.Arch.capitalize()))
\r
1138 for Package in DependentPackageList:
\r
1139 PackageDir = os.path.join(self.WorkspaceDir, path.dirname(Package.DescFilePath))
\r
1140 IncludePathList.append(PackageDir)
\r
1141 for Inc in Package.Includes:
\r
1142 Inc = os.path.join(PackageDir, Inc)
\r
1143 if Inc not in IncludePathList:
\r
1144 IncludePathList.append(Inc)
\r
1145 return IncludePathList
\r
1147 ## Create makefile for the module and its dependent libraries
\r
1149 # @param CreateLibraryMakeFile Flag indicating if or not the makefiles of
\r
1150 # dependent libraries will be created
\r
1152 def CreateMakeFile(self, CreateLibraryMakeFile=True):
\r
1153 if self.IsMakeFileCreated:
\r
1156 PlatformInfo = self.BuildInfo.PlatformInfo
\r
1157 if CreateLibraryMakeFile:
\r
1158 for Lib in self.BuildInfo.DependentLibraryList:
\r
1159 EdkLogger.debug(EdkLogger.DEBUG_1, "###" + str(Lib))
\r
1160 LibraryAutoGen = ModuleAutoGen.New(self.Workspace, self.Platform, Lib,
\r
1161 self.BuildTarget, self.ToolChain, self.Arch)
\r
1162 if LibraryAutoGen not in self.BuildInfo.LibraryAutoGenList:
\r
1163 self.BuildInfo.LibraryAutoGenList.append(LibraryAutoGen)
\r
1164 LibraryAutoGen.CreateMakeFile()
\r
1166 Makefile = GenMake.Makefile(self.BuildInfo)
\r
1167 if Makefile.Generate():
\r
1168 EdkLogger.verbose("Generated makefile for module %s [%s]" %
\r
1169 (self.BuildInfo.Name, self.BuildInfo.Arch))
\r
1171 EdkLogger.verbose("Skipped the generation of makefile for module %s [%s]" %
\r
1172 (self.BuildInfo.Name, self.BuildInfo.Arch))
\r
1174 self.IsMakeFileCreated = True
\r
1176 ## Create autogen code for the module and its dependent libraries
\r
1178 # @param CreateLibraryCodeFile Flag indicating if or not the code of
\r
1179 # dependent libraries will be created
\r
1181 def CreateCodeFile(self, CreateLibraryCodeFile=True):
\r
1182 if self.IsCodeFileCreated:
\r
1185 PlatformInfo = self.BuildInfo.PlatformInfo
\r
1186 if CreateLibraryCodeFile:
\r
1187 for Lib in self.BuildInfo.DependentLibraryList:
\r
1188 LibraryAutoGen = ModuleAutoGen.New(self.Workspace, self.Platform, Lib,
\r
1189 self.BuildTarget, self.ToolChain, self.Arch)
\r
1190 if LibraryAutoGen not in self.BuildInfo.LibraryAutoGenList:
\r
1191 self.BuildInfo.LibraryAutoGenList.append(LibraryAutoGen)
\r
1192 LibraryAutoGen.CreateCodeFile()
\r
1194 os.chdir(self.BuildInfo.DebugDir)
\r
1196 IgoredAutoGenList = []
\r
1197 if self.AutoGenC.String != "":
\r
1198 if GenC.Generate(gAutoGenCodeFileName, self.AutoGenC.String):
\r
1199 AutoGenList.append(gAutoGenCodeFileName)
\r
1201 IgoredAutoGenList.append(gAutoGenCodeFileName)
\r
1203 if self.AutoGenH.String != "":
\r
1204 if GenC.Generate(gAutoGenHeaderFileName, self.AutoGenH.String):
\r
1205 AutoGenList.append(gAutoGenHeaderFileName)
\r
1207 IgoredAutoGenList.append(gAutoGenHeaderFileName)
\r
1209 os.chdir(self.BuildInfo.OutputDir)
\r
1210 if self.BuildInfo.DepexList != []:
\r
1211 Dpx = GenDepex.DependencyExpression(self.BuildInfo.DepexList, self.BuildInfo.ModuleType, True)
\r
1212 DpxFile = gAutoGenDepexFileName % {"module_name" : self.BuildInfo.Name}
\r
1213 if Dpx.Generate(DpxFile):
\r
1214 AutoGenList.append(DpxFile)
\r
1216 IgoredAutoGenList.append(DpxFile)
\r
1218 if IgoredAutoGenList == []:
\r
1219 EdkLogger.verbose("Generated [%s] files for module %s [%s]" %
\r
1220 (" ".join(AutoGenList), self.BuildInfo.Name, self.BuildInfo.Arch))
\r
1221 elif AutoGenList == []:
\r
1222 EdkLogger.verbose("Skipped the generation of [%s] files for module %s [%s]" %
\r
1223 (" ".join(IgoredAutoGenList), self.BuildInfo.Name, self.BuildInfo.Arch))
\r
1225 EdkLogger.verbose("Generated [%s] (skipped %s) files for module %s [%s]" %
\r
1226 (" ".join(AutoGenList), " ".join(IgoredAutoGenList), self.BuildInfo.Name, self.BuildInfo.Arch))
\r
1228 self.IsCodeFileCreated = True
\r
1229 os.chdir(self.WorkspaceDir)
\r
1230 return AutoGenList
\r
1232 # Version and Copyright
\r
1233 __version_number__ = "0.01"
\r
1234 __version__ = "%prog Version " + __version_number__
\r
1235 __copyright__ = "Copyright (c) 2007, Intel Corporation. All rights reserved."
\r
1237 ## Parse command line options
\r
1239 # Using standard Python module optparse to parse command line option of this tool.
\r
1241 # @retval Options A optparse.Values object containing the parsed options
\r
1242 # @retval InputFile Path of file to be trimmed
\r
1246 make_option("-a", "--arch", dest="Arch",
\r
1247 help="The input file is preprocessed source code, including C or assembly code"),
\r
1248 make_option("-p", "--platform", dest="ActivePlatform",
\r
1249 help="The input file is preprocessed VFR file"),
\r
1250 make_option("-m", "--module", dest="ActiveModule",
\r
1251 help="Convert standard hex format (0xabcd) to MASM format (abcdh)"),
\r
1252 make_option("-f", "--FDF-file", dest="FdfFile",
\r
1253 help="Convert standard hex format (0xabcd) to MASM format (abcdh)"),
\r
1254 make_option("-o", "--output", dest="OutputDirectory",
\r
1255 help="File to store the trimmed content"),
\r
1256 make_option("-t", "--toolchain-tag", dest="ToolChain",
\r
1258 make_option("-k", "--msft", dest="MakefileType", action="store_const", const="nmake",
\r
1260 make_option("-g", "--gcc", dest="MakefileType", action="store_const", const="gmake",
\r
1262 make_option("-v", "--verbose", dest="LogLevel", action="store_const", const=EdkLogger.VERBOSE,
\r
1263 help="Run verbosely"),
\r
1264 make_option("-d", "--debug", dest="LogLevel", type="int",
\r
1265 help="Run with debug information"),
\r
1266 make_option("-q", "--quiet", dest="LogLevel", action="store_const", const=EdkLogger.QUIET,
\r
1267 help="Run quietly"),
\r
1268 make_option("-?", action="help", help="show this help message and exit"),
\r
1271 # use clearer usage to override default usage message
\r
1272 UsageString = "%prog [-a ARCH] [-p PLATFORM] [-m MODULE] [-t TOOLCHAIN_TAG] [-k] [-g] [-v|-d <debug_level>|-q] [-o <output_directory>] [GenC|GenMake]"
\r
1274 Parser = OptionParser(description=__copyright__, version=__version__, option_list=OptionList, usage=UsageString)
\r
1275 Parser.set_defaults(Arch=[])
\r
1276 Parser.set_defaults(ActivePlatform=None)
\r
1277 Parser.set_defaults(ActiveModule=None)
\r
1278 Parser.set_defaults(OutputDirectory="build")
\r
1279 Parser.set_defaults(FdfFile=None)
\r
1280 Parser.set_defaults(ToolChain="MYTOOLS")
\r
1281 if sys.platform == "win32":
\r
1282 Parser.set_defaults(MakefileType="nmake")
\r
1284 Parser.set_defaults(MakefileType="gmake")
\r
1285 Parser.set_defaults(LogLevel=EdkLogger.INFO)
\r
1287 Options, Args = Parser.parse_args()
\r
1290 if len(Args) == 0:
\r
1291 Options.Target = "genmake"
\r
1292 sys.argv.append("genmake")
\r
1293 elif len(Args) == 1:
\r
1294 Options.Target = Args[0].lower()
\r
1295 if Options.Target not in ["genc", "genmake"]:
\r
1296 EdkLogger.error("AutoGen", OPTION_NOT_SUPPORTED, "Not supported target",
\r
1297 ExtraData="%s\n\n%s" % (Options.Target, Parser.get_usage()))
\r
1299 EdkLogger.error("AutoGen", OPTION_NOT_SUPPORTED, "Too many targets",
\r
1300 ExtraData=Parser.get_usage())
\r
1304 ## Entrance method
\r
1306 # This method mainly dispatch specific methods per the command line options.
\r
1307 # If no error found, return zero value so the caller of this tool can know
\r
1308 # if it's executed successfully or not.
\r
1310 # @retval 0 Tool was successful
\r
1311 # @retval 1 Tool failed
\r
1314 from build import build
\r
1316 Option = GetOptions()
\r
1318 except Exception, e:
\r
1324 # This acts like the main() function for the script, unless it is 'import'ed into another script.
\r
1325 if __name__ == '__main__':
\r