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