]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/AutoGen/AutoGen.py
Sync basetools' source and binary files with r1707 of the basetools project.
[mirror_edk2.git] / BaseTools / Source / Python / AutoGen / AutoGen.py
CommitLineData
30fdf114
LG
1## @file
2# Generate AutoGen.h, AutoGen.c and *.depex files
3#
030529de 4# Copyright (c) 2007 - 2009, Intel Corporation
30fdf114
LG
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 = {}
fd171542 1064 FamilyMatch = False
1065 FamilyIsNull = True
30fdf114
LG
1066 for Key in Options:
1067 Family = Key[0]
1068 Target, Tag, Arch, Tool, Attr = Key[1].split("_")
1069 # if tool chain family doesn't match, skip it
fd171542 1070 if Tool in self.ToolDefinition and Family != "":
1071 FamilyIsNull = False
1072 if self.ToolDefinition[Tool].get(TAB_TOD_DEFINES_BUILDRULEFAMILY, "") != "":
1073 if Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_BUILDRULEFAMILY]:
1074 continue
1075 elif Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_FAMILY]:
1076 continue
1077 FamilyMatch = True
1078 # expand any wildcard
1079 if Target == "*" or Target == self.BuildTarget:
1080 if Tag == "*" or Tag == self.ToolChain:
1081 if Arch == "*" or Arch == self.Arch:
1082 if Tool not in BuildOptions:
1083 BuildOptions[Tool] = {}
1084 if Attr != "FLAGS" or Attr not in BuildOptions[Tool]:
1085 BuildOptions[Tool][Attr] = Options[Key]
1086 else:
1087 # append options for the same tool
1088 BuildOptions[Tool][Attr] += " " + Options[Key]
1089 # Build Option Family has been checked, which need't to be checked again for family.
1090 if FamilyMatch or FamilyIsNull:
1091 return BuildOptions
1092
1093 for Key in Options:
1094 Family = Key[0]
1095 Target, Tag, Arch, Tool, Attr = Key[1].split("_")
1096 # if tool chain family doesn't match, skip it
1097 if Tool not in self.ToolDefinition or Family =="":
30fdf114 1098 continue
fd171542 1099 # option has been added before
1100 if Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_FAMILY]:
1101 continue
1102
30fdf114
LG
1103 # expand any wildcard
1104 if Target == "*" or Target == self.BuildTarget:
1105 if Tag == "*" or Tag == self.ToolChain:
1106 if Arch == "*" or Arch == self.Arch:
1107 if Tool not in BuildOptions:
1108 BuildOptions[Tool] = {}
1109 if Attr != "FLAGS" or Attr not in BuildOptions[Tool]:
1110 BuildOptions[Tool][Attr] = Options[Key]
1111 else:
1112 # append options for the same tool
1113 BuildOptions[Tool][Attr] += " " + Options[Key]
1114 return BuildOptions
1115
1116 ## Append build options in platform to a module
1117 #
1118 # @param Module The module to which the build options will be appened
1119 #
1120 # @retval options The options appended with build options in platform
1121 #
1122 def ApplyBuildOption(self, Module):
1123 PlatformOptions = self.BuildOption
1124 ModuleOptions = self._ExpandBuildOption(Module.BuildOptions)
1125 if Module in self.Platform.Modules:
1126 PlatformModule = self.Platform.Modules[str(Module)]
1127 PlatformModuleOptions = self._ExpandBuildOption(PlatformModule.BuildOptions)
1128 else:
1129 PlatformModuleOptions = {}
1130
1131 AllTools = set(ModuleOptions.keys() + PlatformOptions.keys() + PlatformModuleOptions.keys() + self.ToolDefinition.keys())
1132 BuildOptions = {}
1133 for Tool in AllTools:
1134 if Tool not in BuildOptions:
1135 BuildOptions[Tool] = {}
1136
1137 for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, PlatformModuleOptions]:
1138 if Tool not in Options:
1139 continue
1140 for Attr in Options[Tool]:
1141 Value = Options[Tool][Attr]
1142 if Attr not in BuildOptions[Tool]:
1143 BuildOptions[Tool][Attr] = ""
1144 # check if override is indicated
1145 if Value.startswith('='):
1146 BuildOptions[Tool][Attr] = Value[1:]
1147 else:
1148 BuildOptions[Tool][Attr] += " " + Value
1149 return BuildOptions
1150
1151 Platform = property(_GetPlatform)
1152 Name = property(_GetName)
1153 Guid = property(_GetGuid)
1154 Version = property(_GetVersion)
1155
1156 OutputDir = property(_GetOutputDir)
1157 BuildDir = property(_GetBuildDir)
1158 MakeFileDir = property(_GetMakeFileDir)
1159 FdfFile = property(_GetFdfFile)
1160
1161 PcdTokenNumber = property(_GetPcdTokenNumbers) # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber
1162 DynamicPcdList = property(_GetDynamicPcdList) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1163 NonDynamicPcdList = property(_GetNonDynamicPcdList) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1164 PackageList = property(_GetPackageList)
1165
1166 ToolDefinition = property(_GetToolDefinition) # toolcode : tool path
1167 ToolDefinitionFile = property(_GetToolDefFile) # toolcode : lib path
1168 ToolChainFamily = property(_GetToolChainFamily)
1169 BuildRuleFamily = property(_GetBuildRuleFamily)
1170 BuildOption = property(_GetBuildOptions) # toolcode : option
1171
1172 BuildCommand = property(_GetBuildCommand)
1173 BuildRule = property(_GetBuildRule)
1174 ModuleAutoGenList = property(_GetModuleAutoGenList)
1175 LibraryAutoGenList = property(_GetLibraryAutoGenList)
1176
1177## ModuleAutoGen class
1178#
1179# This class encapsules the AutoGen behaviors for the build tools. In addition to
1180# the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according
1181# to the [depex] section in module's inf file.
1182#
1183class ModuleAutoGen(AutoGen):
1184 ## The real constructor of ModuleAutoGen
1185 #
1186 # This method is not supposed to be called by users of ModuleAutoGen. It's
1187 # only used by factory method __new__() to do real initialization work for an
1188 # object of ModuleAutoGen
1189 #
1190 # @param Workspace EdkIIWorkspaceBuild object
1191 # @param ModuleFile The path of module file
1192 # @param Target Build target (DEBUG, RELEASE)
1193 # @param Toolchain Name of tool chain
1194 # @param Arch The arch the module supports
1195 # @param PlatformFile Platform meta-file
1196 #
1197 def _Init(self, Workspace, ModuleFile, Target, Toolchain, Arch, PlatformFile):
1198 EdkLogger.debug(EdkLogger.DEBUG_9, "AutoGen module [%s] [%s]" % (ModuleFile, Arch))
1199 GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (ModuleFile, Arch, Toolchain, Target)
1200
1201 self.Workspace = Workspace
1202 self.WorkspaceDir = Workspace.WorkspaceDir
1203
1204 self.MetaFile = ModuleFile
1205 self.PlatformInfo = PlatformAutoGen(Workspace, PlatformFile, Target, Toolchain, Arch)
1206 # check if this module is employed by active platform
1207 if not self.PlatformInfo.ValidModule(self.MetaFile):
1208 EdkLogger.verbose("Module [%s] for [%s] is not employed by active platform\n" \
1209 % (self.MetaFile, Arch))
1210 return False
1211
1212 self.SourceDir = self.MetaFile.SubDir
1213 self.SourceOverrideDir = None
1214 # use overrided path defined in DSC file
1215 if self.MetaFile.Key in GlobalData.gOverrideDir:
1216 self.SourceOverrideDir = GlobalData.gOverrideDir[self.MetaFile.Key]
1217
1218 self.ToolChain = Toolchain
1219 self.BuildTarget = Target
1220 self.Arch = Arch
1221 self.ToolChainFamily = self.PlatformInfo.ToolChainFamily
1222 self.BuildRuleFamily = self.PlatformInfo.BuildRuleFamily
1223
1224 self.IsMakeFileCreated = False
1225 self.IsCodeFileCreated = False
1226
1227 self.BuildDatabase = self.Workspace.BuildDatabase
1228
1229 self._Module = None
1230 self._Name = None
1231 self._Guid = None
1232 self._Version = None
1233 self._ModuleType = None
1234 self._ComponentType = None
1235 self._PcdIsDriver = None
1236 self._AutoGenVersion = None
1237 self._LibraryFlag = None
1238 self._CustomMakefile = None
1239 self._Macro = None
1240
1241 self._BuildDir = None
1242 self._OutputDir = None
1243 self._DebugDir = None
1244 self._MakeFileDir = None
1245
1246 self._IncludePathList = None
1247 self._AutoGenFileList = None
1248 self._UnicodeFileList = None
1249 self._SourceFileList = None
1250 self._ObjectFileList = None
1251 self._BinaryFileList = None
1252
1253 self._DependentPackageList = None
1254 self._DependentLibraryList = None
1255 self._LibraryAutoGenList = None
1256 self._DerivedPackageList = None
1257 self._ModulePcdList = None
1258 self._LibraryPcdList = None
1259 self._GuidList = None
1260 self._ProtocolList = None
1261 self._PpiList = None
1262 self._DepexList = None
1263 self._BuildOption = None
1264 self._BuildTargets = None
1265 self._IntroBuildTargetList = None
1266 self._FinalBuildTargetList = None
1267 self._FileTypes = None
1268 self._BuildRules = None
1269
1270 return True
1271
1272 def __repr__(self):
1273 return "%s [%s]" % (self.MetaFile, self.Arch)
1274
1275 # Macros could be used in build_rule.txt (also Makefile)
1276 def _GetMacros(self):
1277 if self._Macro == None:
1278 self._Macro = sdict()
1279 self._Macro["WORKSPACE" ] = self.WorkspaceDir
1280 self._Macro["MODULE_NAME" ] = self.Name
1281 self._Macro["MODULE_GUID" ] = self.Guid
1282 self._Macro["MODULE_VERSION" ] = self.Version
1283 self._Macro["MODULE_TYPE" ] = self.ModuleType
1284 self._Macro["MODULE_FILE" ] = str(self.MetaFile)
1285 self._Macro["MODULE_FILE_BASE_NAME" ] = self.MetaFile.BaseName
1286 self._Macro["MODULE_RELATIVE_DIR" ] = self.SourceDir
1287 self._Macro["MODULE_DIR" ] = self.SourceDir
1288
1289 self._Macro["BASE_NAME" ] = self.Name
1290
1291 self._Macro["ARCH" ] = self.Arch
1292 self._Macro["TOOLCHAIN" ] = self.ToolChain
1293 self._Macro["TOOLCHAIN_TAG" ] = self.ToolChain
1294 self._Macro["TARGET" ] = self.BuildTarget
1295
1296 self._Macro["BUILD_DIR" ] = self.PlatformInfo.BuildDir
1297 self._Macro["BIN_DIR" ] = os.path.join(self.PlatformInfo.BuildDir, self.Arch)
1298 self._Macro["LIB_DIR" ] = os.path.join(self.PlatformInfo.BuildDir, self.Arch)
1299 self._Macro["MODULE_BUILD_DIR" ] = self.BuildDir
1300 self._Macro["OUTPUT_DIR" ] = self.OutputDir
1301 self._Macro["DEBUG_DIR" ] = self.DebugDir
1302 return self._Macro
1303
1304 ## Return the module build data object
1305 def _GetModule(self):
1306 if self._Module == None:
1307 self._Module = self.Workspace.BuildDatabase[self.MetaFile, self.Arch]
1308 return self._Module
1309
1310 ## Return the module name
1311 def _GetBaseName(self):
1312 return self.Module.BaseName
1313
1314 ## Return the module SourceOverridePath
1315 def _GetSourceOverridePath(self):
1316 return self.Module.SourceOverridePath
1317
1318 ## Return the module meta-file GUID
1319 def _GetGuid(self):
1320 return self.Module.Guid
1321
1322 ## Return the module version
1323 def _GetVersion(self):
1324 return self.Module.Version
1325
1326 ## Return the module type
1327 def _GetModuleType(self):
1328 return self.Module.ModuleType
1329
1330 ## Return the component type (for R8.x style of module)
1331 def _GetComponentType(self):
1332 return self.Module.ComponentType
1333
1334 ## Return the build type
1335 def _GetBuildType(self):
1336 return self.Module.BuildType
1337
1338 ## Return the PCD_IS_DRIVER setting
1339 def _GetPcdIsDriver(self):
1340 return self.Module.PcdIsDriver
1341
1342 ## Return the autogen version, i.e. module meta-file version
1343 def _GetAutoGenVersion(self):
1344 return self.Module.AutoGenVersion
1345
1346 ## Check if the module is library or not
1347 def _IsLibrary(self):
1348 if self._LibraryFlag == None:
1349 if self.Module.LibraryClass != None and self.Module.LibraryClass != []:
1350 self._LibraryFlag = True
1351 else:
1352 self._LibraryFlag = False
1353 return self._LibraryFlag
1354
1355 ## Return the directory to store intermediate files of the module
1356 def _GetBuildDir(self):
1357 if self._BuildDir == None:
1358 self._BuildDir = path.join(
1359 self.PlatformInfo.BuildDir,
1360 self.Arch,
1361 self.SourceDir,
1362 self.MetaFile.BaseName
1363 )
1364 CreateDirectory(self._BuildDir)
1365 return self._BuildDir
1366
1367 ## Return the directory to store the intermediate object files of the mdoule
1368 def _GetOutputDir(self):
1369 if self._OutputDir == None:
1370 self._OutputDir = path.join(self.BuildDir, "OUTPUT")
1371 CreateDirectory(self._OutputDir)
1372 return self._OutputDir
1373
1374 ## Return the directory to store auto-gened source files of the mdoule
1375 def _GetDebugDir(self):
1376 if self._DebugDir == None:
1377 self._DebugDir = path.join(self.BuildDir, "DEBUG")
1378 CreateDirectory(self._DebugDir)
1379 return self._DebugDir
1380
1381 ## Return the path of custom file
1382 def _GetCustomMakefile(self):
1383 if self._CustomMakefile == None:
1384 self._CustomMakefile = {}
1385 for Type in self.Module.CustomMakefile:
1386 if Type in gMakeTypeMap:
1387 MakeType = gMakeTypeMap[Type]
1388 else:
1389 MakeType = 'nmake'
1390 if self.SourceOverrideDir != None:
1391 File = os.path.join(self.SourceOverrideDir, self.Module.CustomMakefile[Type])
1392 if not os.path.exists(File):
1393 File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])
1394 else:
1395 File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])
1396 self._CustomMakefile[MakeType] = File
1397 return self._CustomMakefile
1398
1399 ## Return the directory of the makefile
1400 #
1401 # @retval string The directory string of module's makefile
1402 #
1403 def _GetMakeFileDir(self):
1404 return self.BuildDir
1405
1406 ## Return build command string
1407 #
1408 # @retval string Build command string
1409 #
1410 def _GetBuildCommand(self):
1411 return self.PlatformInfo.BuildCommand
1412
1413 ## Get object list of all packages the module and its dependent libraries belong to
1414 #
1415 # @retval list The list of package object
1416 #
1417 def _GetDerivedPackageList(self):
1418 PackageList = []
1419 for M in [self.Module] + self.DependentLibraryList:
1420 for Package in M.Packages:
1421 if Package in PackageList:
1422 continue
1423 PackageList.append(Package)
1424 return PackageList
1425
1426 ## Merge dependency expression
1427 #
1428 # @retval list The token list of the dependency expression after parsed
1429 #
1430 def _GetDepexTokenList(self):
1431 if self._DepexList == None:
1432 self._DepexList = {}
1433 if self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:
1434 return self._DepexList
1435
1436 if self.ModuleType == "DXE_SMM_DRIVER":
1437 self._DepexList["DXE_DRIVER"] = []
1438 self._DepexList["SMM_DRIVER"] = []
1439 else:
1440 self._DepexList[self.ModuleType] = []
1441
1442 for ModuleType in self._DepexList:
1443 DepexList = self._DepexList[ModuleType]
1444 #
1445 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
1446 #
1447 for M in [self.Module] + self.DependentLibraryList:
1448 Inherited = False
1449 for D in M.Depex[self.Arch, ModuleType]:
1450 if DepexList != []:
1451 DepexList.append('AND')
1452 DepexList.append('(')
1453 DepexList.extend(D)
1454 if DepexList[-1] == 'END': # no need of a END at this time
1455 DepexList.pop()
1456 DepexList.append(')')
1457 Inherited = True
1458 if Inherited:
1459 EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexList))
1460 if 'BEFORE' in DepexList or 'AFTER' in DepexList:
1461 break
1462 if len(DepexList) > 0:
1463 EdkLogger.verbose('')
1464 return self._DepexList
1465
1466 ## Return the list of specification version required for the module
1467 #
1468 # @retval list The list of specification defined in module file
1469 #
1470 def _GetSpecification(self):
1471 return self.Module.Specification
1472
1473 ## Tool option for the module build
1474 #
1475 # @param PlatformInfo The object of PlatformBuildInfo
1476 # @retval dict The dict containing valid options
1477 #
1478 def _GetModuleBuildOption(self):
1479 if self._BuildOption == None:
1480 self._BuildOption = self.PlatformInfo.ApplyBuildOption(self.Module)
1481 return self._BuildOption
1482
1483 ## Return a list of files which can be built from source
1484 #
1485 # What kind of files can be built is determined by build rules in
1486 # $(WORKSPACE)/Conf/build_rule.txt and toolchain family.
1487 #
1488 def _GetSourceFileList(self):
1489 if self._SourceFileList == None:
1490 self._SourceFileList = []
1491 for F in self.Module.Sources:
1492 # match tool chain
1493 if F.TagName != "" and F.TagName != self.ToolChain:
1494 EdkLogger.debug(EdkLogger.DEBUG_9, "The toolchain [%s] for processing file [%s] is found, "
1495 "but [%s] is needed" % (F.TagName, str(F), self.ToolChain))
1496 continue
1497 # match tool chain family
1498 if F.ToolChainFamily != "" and F.ToolChainFamily != self.ToolChainFamily:
1499 EdkLogger.debug(
1500 EdkLogger.DEBUG_0,
1501 "The file [%s] must be built by tools of [%s], " \
1502 "but current toolchain family is [%s]" \
1503 % (str(F), F.ToolChainFamily, self.ToolChainFamily))
1504 continue
1505
1506 # add the file path into search path list for file including
1507 if F.Dir not in self.IncludePathList and self.AutoGenVersion >= 0x00010005:
1508 self.IncludePathList.insert(0, F.Dir)
1509 self._SourceFileList.append(F)
1510 self._ApplyBuildRule(F, TAB_UNKNOWN_FILE)
1511 return self._SourceFileList
1512
1513 ## Return the list of unicode files
1514 def _GetUnicodeFileList(self):
1515 if self._UnicodeFileList == None:
1516 if TAB_UNICODE_FILE in self.FileTypes:
1517 self._UnicodeFileList = self.FileTypes[TAB_UNICODE_FILE]
1518 else:
1519 self._UnicodeFileList = []
1520 return self._UnicodeFileList
1521
1522 ## Return a list of files which can be built from binary
1523 #
1524 # "Build" binary files are just to copy them to build directory.
1525 #
1526 # @retval list The list of files which can be built later
1527 #
1528 def _GetBinaryFiles(self):
1529 if self._BinaryFileList == None:
1530 self._BinaryFileList = []
1531 for F in self.Module.Binaries:
1532 if F.Target not in ['COMMON', '*'] and F.Target != self.BuildTarget:
1533 continue
1534 self._BinaryFileList.append(F)
1535 self._ApplyBuildRule(F, F.Type)
1536 return self._BinaryFileList
1537
1538 def _GetBuildRules(self):
1539 if self._BuildRules == None:
1540 BuildRules = {}
1541 BuildRuleDatabase = self.PlatformInfo.BuildRule
1542 for Type in BuildRuleDatabase.FileTypeList:
1543 #first try getting build rule by BuildRuleFamily
1544 RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.BuildRuleFamily]
1545 if not RuleObject:
1546 # build type is always module type, but ...
1547 if self.ModuleType != self.BuildType:
1548 RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.BuildRuleFamily]
1549 #second try getting build rule by ToolChainFamily
1550 if not RuleObject:
1551 RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.ToolChainFamily]
1552 if not RuleObject:
1553 # build type is always module type, but ...
1554 if self.ModuleType != self.BuildType:
1555 RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.ToolChainFamily]
1556 if not RuleObject:
1557 continue
1558 RuleObject = RuleObject.Instantiate(self.Macros)
1559 BuildRules[Type] = RuleObject
1560 for Ext in RuleObject.SourceFileExtList:
1561 BuildRules[Ext] = RuleObject
1562 self._BuildRules = BuildRules
1563 return self._BuildRules
1564
1565 def _ApplyBuildRule(self, File, FileType):
1566 if self._BuildTargets == None:
1567 self._IntroBuildTargetList = set()
1568 self._FinalBuildTargetList = set()
1569 self._BuildTargets = {}
1570 self._FileTypes = {}
1571
1572 LastTarget = None
1573 RuleChain = []
1574 SourceList = [File]
1575 Index = 0
1576 while Index < len(SourceList):
1577 Source = SourceList[Index]
1578 Index = Index + 1
1579
1580 if Source != File:
1581 CreateDirectory(Source.Dir)
1582
1583 if FileType in self.BuildRules:
1584 RuleObject = self.BuildRules[FileType]
1585 elif Source.Ext in self.BuildRules:
1586 RuleObject = self.BuildRules[Source.Ext]
1587 elif File.IsBinary and File == Source:
1588 RuleObject = self.BuildRules[TAB_DEFAULT_BINARY_FILE]
1589 else:
1590 # stop at no more rules
1591 if LastTarget:
1592 self._FinalBuildTargetList.add(LastTarget)
1593 break
1594
1595 FileType = RuleObject.SourceFileType
1596 if FileType not in self._FileTypes:
1597 self._FileTypes[FileType] = set()
1598 self._FileTypes[FileType].add(Source)
1599
1600 # stop at STATIC_LIBRARY for library
1601 if self.IsLibrary and FileType == TAB_STATIC_LIBRARY:
1602 self._FinalBuildTargetList.add(LastTarget)
1603 break
1604
1605 Target = RuleObject.Apply(Source)
1606 if not Target:
1607 if LastTarget:
1608 self._FinalBuildTargetList.add(LastTarget)
1609 break
1610 elif not Target.Outputs:
1611 # Only do build for target with outputs
1612 self._FinalBuildTargetList.add(Target)
1613
1614 if FileType not in self._BuildTargets:
1615 self._BuildTargets[FileType] = set()
1616 self._BuildTargets[FileType].add(Target)
1617
1618 if not Source.IsBinary and Source == File:
1619 self._IntroBuildTargetList.add(Target)
1620
1621 # to avoid cyclic rule
1622 if FileType in RuleChain:
1623 break
1624
1625 RuleChain.append(FileType)
1626 SourceList.extend(Target.Outputs)
1627 LastTarget = Target
1628 FileType = TAB_UNKNOWN_FILE
1629
1630 def _GetTargets(self):
1631 if self._BuildTargets == None:
1632 self._IntroBuildTargetList = set()
1633 self._FinalBuildTargetList = set()
1634 self._BuildTargets = {}
1635 self._FileTypes = {}
1636
1637 #TRICK: call _GetSourceFileList to apply build rule for binary files
1638 if self.SourceFileList:
1639 pass
1640
1641 #TRICK: call _GetBinaryFileList to apply build rule for binary files
1642 if self.BinaryFileList:
1643 pass
1644
1645 return self._BuildTargets
1646
1647 def _GetIntroTargetList(self):
1648 self._GetTargets()
1649 return self._IntroBuildTargetList
1650
1651 def _GetFinalTargetList(self):
1652 self._GetTargets()
1653 return self._FinalBuildTargetList
1654
1655 def _GetFileTypes(self):
1656 self._GetTargets()
1657 return self._FileTypes
1658
1659 ## Get the list of package object the module depends on
1660 #
1661 # @retval list The package object list
1662 #
1663 def _GetDependentPackageList(self):
1664 return self.Module.Packages
1665
1666 ## Return the list of auto-generated code file
1667 #
1668 # @retval list The list of auto-generated file
1669 #
1670 def _GetAutoGenFileList(self):
1671 if self._AutoGenFileList == None:
1672 self._AutoGenFileList = {}
1673 AutoGenC = TemplateString()
1674 AutoGenH = TemplateString()
1675 StringH = TemplateString()
1676 GenC.CreateCode(self, AutoGenC, AutoGenH, StringH)
1677 if str(AutoGenC) != "" and TAB_C_CODE_FILE in self.FileTypes:
1678 AutoFile = PathClass(gAutoGenCodeFileName, self.DebugDir)
1679 self._AutoGenFileList[AutoFile] = str(AutoGenC)
1680 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
1681 if str(AutoGenH) != "":
1682 AutoFile = PathClass(gAutoGenHeaderFileName, self.DebugDir)
1683 self._AutoGenFileList[AutoFile] = str(AutoGenH)
1684 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
1685 if str(StringH) != "":
1686 AutoFile = PathClass(gAutoGenStringFileName % {"module_name":self.Name}, self.DebugDir)
1687 self._AutoGenFileList[AutoFile] = str(StringH)
1688 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
1689 return self._AutoGenFileList
1690
1691 ## Return the list of library modules explicitly or implicityly used by this module
1692 def _GetLibraryList(self):
1693 if self._DependentLibraryList == None:
1694 # only merge library classes and PCD for non-library module
1695 if self.IsLibrary:
1696 self._DependentLibraryList = []
1697 else:
1698 if self.AutoGenVersion < 0x00010005:
1699 self._DependentLibraryList = self.PlatformInfo.ResolveLibraryReference(self.Module)
1700 else:
1701 self._DependentLibraryList = self.PlatformInfo.ApplyLibraryInstance(self.Module)
1702 return self._DependentLibraryList
1703
1704 ## Get the list of PCDs from current module
1705 #
1706 # @retval list The list of PCD
1707 #
1708 def _GetModulePcdList(self):
1709 if self._ModulePcdList == None:
1710 # apply PCD settings from platform
1711 self._ModulePcdList = self.PlatformInfo.ApplyPcdSetting(self.Module, self.Module.Pcds)
1712 return self._ModulePcdList
1713
1714 ## Get the list of PCDs from dependent libraries
1715 #
1716 # @retval list The list of PCD
1717 #
1718 def _GetLibraryPcdList(self):
1719 if self._LibraryPcdList == None:
1720 Pcds = {}
1721 if not self.IsLibrary:
1722 # get PCDs from dependent libraries
1723 for Library in self.DependentLibraryList:
1724 for Key in Library.Pcds:
1725 # skip duplicated PCDs
1726 if Key in self.Module.Pcds or Key in Pcds:
1727 continue
1728 Pcds[Key] = copy.copy(Library.Pcds[Key])
1729 # apply PCD settings from platform
1730 self._LibraryPcdList = self.PlatformInfo.ApplyPcdSetting(self.Module, Pcds)
1731 else:
1732 self._LibraryPcdList = []
1733 return self._LibraryPcdList
1734
1735 ## Get the GUID value mapping
1736 #
1737 # @retval dict The mapping between GUID cname and its value
1738 #
1739 def _GetGuidList(self):
1740 if self._GuidList == None:
1741 self._GuidList = self.Module.Guids
1742 for Library in self.DependentLibraryList:
1743 self._GuidList.update(Library.Guids)
1744 return self._GuidList
1745
1746 ## Get the protocol value mapping
1747 #
1748 # @retval dict The mapping between protocol cname and its value
1749 #
1750 def _GetProtocolList(self):
1751 if self._ProtocolList == None:
1752 self._ProtocolList = self.Module.Protocols
1753 for Library in self.DependentLibraryList:
1754 self._ProtocolList.update(Library.Protocols)
1755 return self._ProtocolList
1756
1757 ## Get the PPI value mapping
1758 #
1759 # @retval dict The mapping between PPI cname and its value
1760 #
1761 def _GetPpiList(self):
1762 if self._PpiList == None:
1763 self._PpiList = self.Module.Ppis
1764 for Library in self.DependentLibraryList:
1765 self._PpiList.update(Library.Ppis)
1766 return self._PpiList
1767
1768 ## Get the list of include search path
1769 #
1770 # @retval list The list path
1771 #
1772 def _GetIncludePathList(self):
1773 if self._IncludePathList == None:
1774 self._IncludePathList = []
1775 if self.AutoGenVersion < 0x00010005:
1776 for Inc in self.Module.Includes:
1777 if Inc not in self._IncludePathList:
1778 self._IncludePathList.append(Inc)
1779 # for r8 modules
1780 Inc = path.join(Inc, self.Arch.capitalize())
1781 if os.path.exists(Inc) and Inc not in self._IncludePathList:
1782 self._IncludePathList.append(Inc)
1783 # r8 module needs to put DEBUG_DIR at the end of search path and not to use SOURCE_DIR all the time
1784 self._IncludePathList.append(self.DebugDir)
1785 else:
1786 self._IncludePathList.append(self.MetaFile.Dir)
1787 self._IncludePathList.append(self.DebugDir)
1788
1789 for Package in self.Module.Packages:
1790 PackageDir = path.join(self.WorkspaceDir, Package.MetaFile.Dir)
1791 if PackageDir not in self._IncludePathList:
1792 self._IncludePathList.append(PackageDir)
1793 for Inc in Package.Includes:
1794 if Inc not in self._IncludePathList:
1795 self._IncludePathList.append(str(Inc))
1796 return self._IncludePathList
1797
1798 ## Create makefile for the module and its dependent libraries
1799 #
1800 # @param CreateLibraryMakeFile Flag indicating if or not the makefiles of
1801 # dependent libraries will be created
1802 #
1803 def CreateMakeFile(self, CreateLibraryMakeFile=True):
1804 if self.IsMakeFileCreated:
1805 return
1806
1807 if not self.IsLibrary and CreateLibraryMakeFile:
1808 for LibraryAutoGen in self.LibraryAutoGenList:
1809 LibraryAutoGen.CreateMakeFile()
1810
1811 if len(self.CustomMakefile) == 0:
1812 Makefile = GenMake.ModuleMakefile(self)
1813 else:
1814 Makefile = GenMake.CustomMakefile(self)
1815 if Makefile.Generate():
1816 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated makefile for module %s [%s]" %
1817 (self.Name, self.Arch))
1818 else:
1819 EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of makefile for module %s [%s]" %
1820 (self.Name, self.Arch))
1821
1822 self.IsMakeFileCreated = True
1823
1824 ## Create autogen code for the module and its dependent libraries
1825 #
1826 # @param CreateLibraryCodeFile Flag indicating if or not the code of
1827 # dependent libraries will be created
1828 #
1829 def CreateCodeFile(self, CreateLibraryCodeFile=True):
1830 if self.IsCodeFileCreated:
1831 return
1832
1833 if not self.IsLibrary and CreateLibraryCodeFile:
1834 for LibraryAutoGen in self.LibraryAutoGenList:
1835 LibraryAutoGen.CreateCodeFile()
1836
1837 AutoGenList = []
1838 IgoredAutoGenList = []
1839
1840 for File in self.AutoGenFileList:
1841 if GenC.Generate(File.Path, self.AutoGenFileList[File]):
1842 #Ignore R8 AutoGen.c
1843 if self.AutoGenVersion < 0x00010005 and File.Name == 'AutoGen.c':
1844 continue
1845
1846 AutoGenList.append(str(File))
1847 else:
1848 IgoredAutoGenList.append(str(File))
1849
030529de 1850 # Skip the following code for EDK I inf
1851 if self.AutoGenVersion < 0x00010005:
1852 return
1853
30fdf114
LG
1854 for ModuleType in self.DepexList:
1855 if len(self.DepexList[ModuleType]) == 0:
1856 continue
1857 Dpx = GenDepex.DependencyExpression(self.DepexList[ModuleType], ModuleType, True)
1858 if ModuleType == 'SMM_DRIVER':
1859 DpxFile = gAutoGenSmmDepexFileName % {"module_name" : self.Name}
1860 else:
1861 DpxFile = gAutoGenDepexFileName % {"module_name" : self.Name}
1862
1863 if Dpx.Generate(path.join(self.OutputDir, DpxFile)):
1864 AutoGenList.append(str(DpxFile))
1865 else:
1866 IgoredAutoGenList.append(str(DpxFile))
1867
1868 if IgoredAutoGenList == []:
1869 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated [%s] files for module %s [%s]" %
1870 (" ".join(AutoGenList), self.Name, self.Arch))
1871 elif AutoGenList == []:
1872 EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of [%s] files for module %s [%s]" %
1873 (" ".join(IgoredAutoGenList), self.Name, self.Arch))
1874 else:
1875 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated [%s] (skipped %s) files for module %s [%s]" %
1876 (" ".join(AutoGenList), " ".join(IgoredAutoGenList), self.Name, self.Arch))
1877
1878 self.IsCodeFileCreated = True
1879 return AutoGenList
1880
1881 ## Summarize the ModuleAutoGen objects of all libraries used by this module
1882 def _GetLibraryAutoGenList(self):
1883 if self._LibraryAutoGenList == None:
1884 self._LibraryAutoGenList = []
1885 for Library in self.DependentLibraryList:
1886 La = ModuleAutoGen(
1887 self.Workspace,
1888 Library.MetaFile,
1889 self.BuildTarget,
1890 self.ToolChain,
1891 self.Arch,
1892 self.PlatformInfo.MetaFile
1893 )
1894 if La not in self._LibraryAutoGenList:
1895 self._LibraryAutoGenList.append(La)
1896 for Lib in La.CodaTargetList:
1897 self._ApplyBuildRule(Lib.Target, TAB_UNKNOWN_FILE)
1898 return self._LibraryAutoGenList
1899
1900 ## Return build command string
1901 #
1902 # @retval string Build command string
1903 #
1904 def _GetBuildCommand(self):
1905 return self.PlatformInfo.BuildCommand
1906
1907
1908 Module = property(_GetModule)
1909 Name = property(_GetBaseName)
1910 Guid = property(_GetGuid)
1911 Version = property(_GetVersion)
1912 ModuleType = property(_GetModuleType)
1913 ComponentType = property(_GetComponentType)
1914 BuildType = property(_GetBuildType)
1915 PcdIsDriver = property(_GetPcdIsDriver)
1916 AutoGenVersion = property(_GetAutoGenVersion)
1917 Macros = property(_GetMacros)
1918 Specification = property(_GetSpecification)
1919
1920 IsLibrary = property(_IsLibrary)
1921
1922 BuildDir = property(_GetBuildDir)
1923 OutputDir = property(_GetOutputDir)
1924 DebugDir = property(_GetDebugDir)
1925 MakeFileDir = property(_GetMakeFileDir)
1926 CustomMakefile = property(_GetCustomMakefile)
1927
1928 IncludePathList = property(_GetIncludePathList)
1929 AutoGenFileList = property(_GetAutoGenFileList)
1930 UnicodeFileList = property(_GetUnicodeFileList)
1931 SourceFileList = property(_GetSourceFileList)
1932 BinaryFileList = property(_GetBinaryFiles) # FileType : [File List]
1933 Targets = property(_GetTargets)
1934 IntroTargetList = property(_GetIntroTargetList)
1935 CodaTargetList = property(_GetFinalTargetList)
1936 FileTypes = property(_GetFileTypes)
1937 BuildRules = property(_GetBuildRules)
1938
1939 DependentPackageList = property(_GetDependentPackageList)
1940 DependentLibraryList = property(_GetLibraryList)
1941 LibraryAutoGenList = property(_GetLibraryAutoGenList)
1942 DerivedPackageList = property(_GetDerivedPackageList)
1943
1944 ModulePcdList = property(_GetModulePcdList)
1945 LibraryPcdList = property(_GetLibraryPcdList)
1946 GuidList = property(_GetGuidList)
1947 ProtocolList = property(_GetProtocolList)
1948 PpiList = property(_GetPpiList)
1949 DepexList = property(_GetDepexTokenList)
1950 BuildOption = property(_GetModuleBuildOption)
1951 BuildCommand = property(_GetBuildCommand)
1952
1953# This acts like the main() function for the script, unless it is 'import'ed into another script.
1954if __name__ == '__main__':
1955 pass
1956