931502c7587dc4015379391241c2d7ccfd91bb2f
[people/mcb30/basetools.git] / Source / Python / Common / EdkIIWorkspaceBuild.py
1 # Copyright (c) 2007, Intel Corporation\r
2 # All rights reserved. This program and the accompanying materials\r
3 # are licensed and made available under the terms and conditions of the BSD License\r
4 # which accompanies this distribution.    The full text of the license may be found at\r
5 # http://opensource.org/licenses/bsd-license.php\r
6 #\r
7 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
8 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
9 \r
10 #\r
11 # This file is used to define each component of the build database\r
12 #\r
13 \r
14 #\r
15 # Import Modules\r
16 #\r
17 import os, string, copy, pdb, copy\r
18 import EdkLogger\r
19 import DataType\r
20 from InfClassObject import *\r
21 from DecClassObject import *\r
22 from DscClassObject import *\r
23 from String import *\r
24 from BuildToolError import *\r
25 from Misc import sdict\r
26 from CommonDataClass.CommonClass import *\r
27 \r
28 #\r
29 # This Class is used for PcdObject\r
30 #\r
31 class PcdClassObject(object):\r
32     def __init__(self, Name = None, Guid = None, Type = None, DatumType = None, Value = None, Token = None, MaxDatumSize = None, SkuInfoList = {}, IsOverrided = False):\r
33         self.TokenCName = Name\r
34         self.TokenSpaceGuidCName = Guid\r
35         self.Type = Type\r
36         self.DatumType = DatumType\r
37         self.DefaultValue = Value\r
38         self.TokenValue = Token\r
39         self.MaxDatumSize = MaxDatumSize\r
40         self.SkuInfoList = SkuInfoList\r
41         self.IsOverrided = IsOverrided\r
42         self.Phase = "DXE"\r
43 \r
44     def __str__(self):\r
45         rtn = '\tTokenCName=' + str(self.TokenCName) + ', ' + \\r
46               'TokenSpaceGuidCName=' + str(self.TokenSpaceGuidCName) + ', ' + \\r
47               'Type=' + str(self.Type) + ', ' + \\r
48               'DatumType=' + str(self.DatumType) + ', ' + \\r
49               'DefaultValue=' + str(self.DefaultValue) + ', ' + \\r
50               'TokenValue=' + str(self.TokenValue) + ', ' + \\r
51               'MaxDatumSize=' + str(self.MaxDatumSize) + ', '\r
52         for Item in self.SkuInfoList.values():\r
53             rtn = rtn + 'SkuId=' + Item.SkuId + ', ' + 'SkuIdName=' + Item.SkuIdName\r
54         rtn = rtn + str(self.IsOverrided)\r
55 \r
56         return rtn\r
57 \r
58     def __eq__(self, other):\r
59         return other != None and self.TokenCName == other.TokenCName and self.TokenSpaceGuidCName == other.TokenSpaceGuidCName\r
60 \r
61     def __hash__(self):\r
62         return hash((self.TokenCName, self.TokenSpaceGuidCName))\r
63 \r
64 #\r
65 # This Class is used for LibraryClassObject\r
66 #\r
67 class LibraryClassObject(object):\r
68     def __init__(self, Name = None, SupModList = [], Type = None):\r
69         self.LibraryClass = Name\r
70         self.SupModList = SupModList\r
71         if Type != None:\r
72             self.SupModList = CleanString(Type).split(DataType.TAB_SPACE_SPLIT)\r
73 \r
74 class ModuleBuildClassObject(object):\r
75     def __init__(self):\r
76         self.DescFilePath            = ''\r
77         self.BaseName                = ''\r
78         self.ModuleType              = ''\r
79         self.Guid                    = ''\r
80         self.Version                 = ''\r
81         self.PcdIsDriver             = ''\r
82         self.BinaryModule            = ''\r
83         self.CustomMakefile          = {}\r
84         self.Specification           = {}\r
85         self.LibraryClass            = []      # [ LibraryClassObject, ...]\r
86         self.ModuleEntryPointList    = []\r
87         self.ModuleUnloadImageList   = []\r
88         self.ConstructorList         = []\r
89         self.DestructorList          = []\r
90 \r
91         self.Binaries                = []        #[ ModuleBinaryClassObject, ...]\r
92         self.Sources                 = []        #[ ModuleSourceFilesClassObject, ... ]\r
93         self.LibraryClasses          = {}        #{ [LibraryClassName, ModuleType] : LibraryClassInfFile }\r
94         self.Protocols               = []        #[ ProtocolName, ... ]\r
95         self.Ppis                    = []        #[ PpiName, ... ]\r
96         self.Guids                   = []        #[ GuidName, ... ]\r
97         self.Includes                = []        #[ IncludePath, ... ]\r
98         self.Packages                = []        #[ DecFileName, ... ]\r
99         self.Pcds                    = {}        #{ [(PcdCName, PcdGuidCName)] : PcdClassObject}\r
100         self.BuildOptions            = {}        #{ [BuildOptionKey] : BuildOptionValue}\r
101         self.Depex                   = ''\r
102 \r
103     def __str__(self):\r
104         return self.DescFilePath\r
105 \r
106     def __eq__(self, other):\r
107         return self.DescFilePath == str(other)\r
108 \r
109     def __hash__(self):\r
110         return hash(self.DescFilePath)\r
111 \r
112 class PackageBuildClassObject(object):\r
113     def __init__(self):\r
114         self.DescFilePath            = ''\r
115         self.PackageName             = ''\r
116         self.Guid                    = ''\r
117         self.Version                 = ''\r
118 \r
119         self.Protocols               = {}       #{ [ProtocolName] : Protocol Guid, ... }\r
120         self.Ppis                    = {}       #{ [PpiName] : Ppi Guid, ... }\r
121         self.Guids                   = {}       #{ [GuidName] : Guid, ... }\r
122         self.Includes                = []       #[ IncludePath, ... ]\r
123         self.LibraryClasses          = {}       #{ [LibraryClassName] : LibraryClassInfFile }\r
124         self.Pcds                    = {}       #{ [(PcdCName, PcdGuidCName)] : PcdClassObject}\r
125 \r
126     def __str__(self):\r
127         return self.DescFilePath\r
128 \r
129     def __eq__(self, other):\r
130         return self.DescFilePath == str(other)\r
131 \r
132     def __hash__(self):\r
133         return hash(self.DescFilePath)\r
134 \r
135 class PlatformBuildClassObject(object):\r
136     def __init__(self):\r
137         self.DescFilePath            = ''\r
138         self.PlatformName            = ''\r
139         self.Guid                    = ''\r
140         self.Version                 = ''\r
141         self.DscSpecification        = ''\r
142         self.OutputDirectory         = ''\r
143         self.FlashDefinition         = ''\r
144         self.BuildNumber             = ''\r
145         self.MakefileName            = ''\r
146 \r
147         self.SkuIds                  = {}       #{ 'SkuName' : SkuId, '!include' : includefilename, ...}\r
148         self.Modules                 = []       #[ InfFileName, ... ]\r
149         self.Libraries               = []       #[ InfFileName, ... ]\r
150         self.LibraryClasses          = {}       #{ (LibraryClassName, ModuleType) : LibraryClassInfFile }\r
151         self.Pcds                    = {}       #{ [(PcdCName, PcdGuidCName)] : PcdClassObject }\r
152         self.BuildOptions            = {}       #{ [BuildOptionKey] : BuildOptionValue }\r
153 \r
154     def __str__(self):\r
155         return self.DescFilePath\r
156 \r
157     def __eq__(self, other):\r
158         return self.DescFilePath == str(other)\r
159 \r
160     def __hash__(self):\r
161         return hash(self.DescFilePath)\r
162 \r
163 class ItemBuild(object):\r
164     def __init__(self, Arch, Platform = None, Package = None, Module = None):\r
165         self.Arch                    = Arch\r
166         self.PlatformDatabase        = {}        #{ [DscFileName] : PlatformBuildClassObject, ...}\r
167         self.PackageDatabase         = {}        #{ [DecFileName] : PacakgeBuildClassObject, ...}\r
168         self.ModuleDatabase          = {}        #{ [InfFileName] : ModuleBuildClassObject, ...}\r
169 \r
170 #\r
171 # This class is used to parse active platform to init all inf/dec/dsc files\r
172 # Generate module/package/platform databases for build\r
173 #\r
174 class WorkspaceBuild(object):\r
175     def __init__(self, ActivePlatform, WorkspaceDir):\r
176         self.WorkspaceDir            = NormPath(WorkspaceDir)\r
177         self.SupArchList             = []        #[ 'IA32', 'X64', ...]\r
178         self.BuildTarget             = []        #[ 'RELEASE', 'DEBUG']\r
179         self.SkuId                   = ''\r
180         self.Fdf                     = ''\r
181         self.FdTargetList            = []\r
182         self.FvTargetList            = []\r
183         self.TargetTxt               = None\r
184         self.ToolDef                 = None\r
185 \r
186         self.InfDatabase             = {}        #{ [InfFileName] : InfClassObject}\r
187         self.DecDatabase             = {}        #{ [DecFileName] : DecClassObject}\r
188         self.DscDatabase             = {}        #{ [DscFileName] : DscClassObject}\r
189 \r
190         #\r
191         # Init build for all arches\r
192         #\r
193         self.Build                   = {}\r
194         for Arch in DataType.ARCH_LIST:\r
195             self.Build[Arch] = ItemBuild(Arch)\r
196 \r
197         #\r
198         # Get active platform\r
199         #\r
200         DscFileName = NormPath(ActivePlatform)\r
201         File = self.WorkspaceFile(DscFileName)\r
202         if os.path.exists(File) and os.path.isfile(File):\r
203             self.DscDatabase[DscFileName] = Dsc(File, True, True, self.WorkspaceDir)\r
204         else:\r
205             raise ParserError(FILE_NOT_FOUND, name = File)\r
206 \r
207         #\r
208         # Parse platform to get module\r
209         #\r
210         for DscFile in self.DscDatabase.keys():\r
211             Platform = self.DscDatabase[DscFile].Platform\r
212 \r
213             #\r
214             # Get global information\r
215             #\r
216             self.SupArchList = Platform.Header.SupArchList\r
217             self.BuildTarget = Platform.Header.BuildTargets\r
218             self.SkuId = Platform.Header.SkuIdName\r
219             self.Fdf = NormPath(Platform.FlashDefinitionFile.FilePath)\r
220 \r
221             #\r
222             # Get all inf files\r
223             #\r
224             for Item in Platform.LibraryClasses.LibraryList:\r
225                 for Arch in Item.SupArchList:\r
226                     self.AddToInfDatabase(Item.FilePath)\r
227 \r
228             for Item in Platform.Modules.ModuleList:\r
229                 for Arch in Item.SupArchList:\r
230                     #\r
231                     # Add modules\r
232                     #\r
233                     Module = Item.FilePath\r
234                     self.AddToInfDatabase(Module)\r
235                     #\r
236                     # Add library used in modules\r
237                     #\r
238                     for Lib in Item.LibraryClasses.LibraryList:\r
239                         self.AddToInfDatabase(Lib.FilePath)\r
240                         self.UpdateLibraryClassOfModule(Module, Lib.Name, Arch, Lib.FilePath)\r
241 \r
242         #\r
243         # Parse module to get package\r
244         #\r
245         for InfFile in self.InfDatabase.keys():\r
246             Module = self.InfDatabase[InfFile].Module\r
247             #\r
248             # Get all dec\r
249             #\r
250             for Item in Module.PackageDependencies:\r
251                 for Arch in Item.SupArchList:\r
252                     self.AddToDecDatabase(Item.FilePath)\r
253     # End of self.Init()\r
254 \r
255     #\r
256     # Generate PlatformDatabase\r
257     #\r
258     def GenPlatformDatabase(self):\r
259         for Dsc in self.DscDatabase.keys():\r
260             Platform = self.DscDatabase[Dsc].Platform\r
261 \r
262             for Arch in self.SupArchList:\r
263                 pb = PlatformBuildClassObject()\r
264 \r
265                 # Defines\r
266                 pb.DescFilePath = Dsc\r
267                 pb.PlatformName = Platform.Header.Name\r
268                 pb.Guid = Platform.Header.Guid\r
269                 pb.Version = Platform.Header.Version\r
270                 pb.DscSpecification = Platform.Header.DscSpecification\r
271                 pb.OutputDirectory = NormPath(Platform.Header.OutputDirectory)\r
272                 pb.FlashDefinition = NormPath(Platform.FlashDefinitionFile.FilePath)\r
273                 pb.BuildNumber = Platform.Header.BuildNumber\r
274 \r
275                 # SkuId\r
276                 for Key in Platform.SkuInfos.SkuInfoList.keys():\r
277                     pb.SkuIds[Key] = Platform.SkuInfos.SkuInfoList[Key]\r
278 \r
279                 # Module\r
280                 for Item in Platform.Modules.ModuleList:\r
281                     if Arch in Item.SupArchList:\r
282                         pb.Modules.append(NormPath(Item.FilePath))\r
283 \r
284                 # BuildOptions\r
285                 for Item in Platform.BuildOptions.BuildOptionList:\r
286                     if Arch in Item.SupArchList:\r
287                         pb.BuildOptions[(Item.ToolChainFamily, Item.ToolChain)] = Item.Option\r
288 \r
289                 # LibraryClass\r
290                 for Item in Platform.LibraryClasses.LibraryList:\r
291                     SupModuleList = self.FindSupModuleListOfLibraryClass(Item, Platform.LibraryClasses.LibraryList)\r
292                     if Arch in Item.SupArchList:\r
293                         for ModuleType in SupModuleList:\r
294                             pb.LibraryClasses[(Item.Name, ModuleType)] = NormPath(Item.FilePath)\r
295 \r
296                 # Pcds\r
297                 for Item in Platform.DynamicPcdBuildDefinitions:\r
298                     if Arch in Item.SupArchList:\r
299                         Name = Item.CName\r
300                         Guid = Item.TokenSpaceGuidCName\r
301                         Type = Item.ItemType\r
302                         DatumType = Item.DatumType\r
303                         Value = Item.DefaultValue\r
304                         Token = Item.Token\r
305                         MaxDatumSize = Item.MaxDatumSize\r
306                         SkuInfoList = Item.SkuInfoList\r
307                         pb.Pcds[(Name, Guid)] = PcdClassObject(Name, Guid, Type, DatumType, Value, Token, MaxDatumSize, SkuInfoList, False)\r
308 \r
309                 # Add to database\r
310                 self.Build[Arch].PlatformDatabase[Dsc] = pb\r
311                 pb = None\r
312 \r
313     #\r
314     # Generate PackageDatabase\r
315     #\r
316     def GenPackageDatabase(self):\r
317         for Dec in self.DecDatabase.keys():\r
318             Package = self.DecDatabase[Dec].Package\r
319 \r
320             for Arch in self.SupArchList:\r
321                 pb = PackageBuildClassObject()\r
322 \r
323                 # Defines\r
324                 pb.DescFilePath = Dec\r
325                 pb.PackageName = Package.Header.Name\r
326                 pb.Guid = Package.Header.Guid\r
327                 pb.Version = Package.Header.Version\r
328 \r
329                 # Protocols\r
330                 for Item in Package.ProtocolDeclarations:\r
331                     if Arch in Item.SupArchList:\r
332                         pb.Protocols[Item.CName] = Item.Guid\r
333 \r
334                 # Ppis\r
335                 for Item in Package.PpiDeclarations:\r
336                     if Arch in Item.SupArchList:\r
337                         pb.Ppis[Item.CName] = Item.Guid\r
338 \r
339                 # Guids\r
340                 for Item in Package.GuidDeclarations:\r
341                     if Arch in Item.SupArchList:\r
342                         pb.Ppis[Item.CName] = Item.Guid\r
343 \r
344                 # Includes\r
345                 for Item in Package.Includes:\r
346                     if Arch in Item.SupArchList:\r
347                         pb.Includes.append(NormPath(Item.FilePath))\r
348 \r
349                 # LibraryClasses\r
350                 for Item in Package.LibraryClassDeclarations:\r
351                     if Arch in Item.SupArchList:\r
352                         pb.LibraryClasses[Item.LibraryClass] = NormPath(Item.RecommendedInstance)\r
353 \r
354                 # Pcds\r
355                 for Item in Package.PcdDeclarations:\r
356                     if Arch in Item.SupArchList:\r
357                         Name = Item.CName\r
358                         Guid = Item.TokenSpaceGuidCName\r
359                         Type = Item.ItemType\r
360                         DatumType = Item.DatumType\r
361                         Value = Item.DefaultValue\r
362                         Token = Item.Token\r
363                         MaxDatumSize = Item.MaxDatumSize\r
364                         SkuInfoList = Item.SkuInfoList\r
365                         pb.Pcds[(Name, Guid)] = PcdClassObject(Name, Guid, Type, DatumType, Value, Token, MaxDatumSize, SkuInfoList, False)\r
366 \r
367                 # Add to database\r
368                 self.Build[Arch].PackageDatabase[Dec] = pb\r
369                 pb = None\r
370 \r
371     #\r
372     # Generate ModuleDatabase\r
373     #\r
374     def GenModuleDatabase(self, PcdsSet = {}):\r
375         for Inf in self.InfDatabase.keys():\r
376             Module = self.InfDatabase[Inf].Module\r
377 \r
378             for Arch in self.SupArchList:\r
379                 if not self.IsModuleDefinedInPlatform(Inf, Arch):\r
380                     continue\r
381 \r
382                 pb = ModuleBuildClassObject()\r
383 \r
384                 # Defines\r
385                 pb.DescFilePath = Inf\r
386                 pb.BaseName = Module.Header.Name\r
387                 pb.Guid = Module.Header.Guid\r
388                 pb.Version = Module.Header.Version\r
389                 pb.ModuleType = Module.Header.ModuleType\r
390                 pb.PcdIsDriver = Module.Header.PcdIsDriver\r
391                 pb.BinaryModule = Module.Header.BinaryModule\r
392                 pb.CustomMakefile = Module.Header.CustomMakefile\r
393 \r
394                 # Specs os Defines\r
395                 pb.Specification = Module.Header.Specification\r
396                 pb.Specification[TAB_INF_DEFINES_EDK_RELEASE_VERSION] = Module.Header.EdkReleaseVersion\r
397                 pb.Specification[TAB_INF_DEFINES_EFI_SPECIFICATION_VERSION] = Module.Header.EfiSpecificationVersion\r
398 \r
399                 # LibraryClass of Defines\r
400                 for Item in Module.Header.LibraryClass:\r
401                     pb.LibraryClass.append(LibraryClassObject(Item.LibraryClass, Item.SupModuleList, None))\r
402 \r
403                 # Module image and library of Defines\r
404                 for Item in Module.ExternImages:\r
405                     if Item.ModuleEntryPoint != '':\r
406                         pb.ModuleEntryPointList.append(Item.ModuleEntryPoint)\r
407                     if Item.ModuleUnloadImage != '':\r
408                         pb.ModuleUnloadImageList.append(Item.ModuleUnloadImage)\r
409                 for Item in Module.ExternLibraries:\r
410                     if Item.Constructor != '':\r
411                         pb.ConstructorList.append(Item.Constructor)\r
412                     if Item.Destructor != '':\r
413                         pb.DestructorList.append(Item.Destructor)\r
414 \r
415                 # Binaries\r
416                 for Item in Module.Binaries:\r
417                     if Arch in Item.SupArchList:\r
418                         FileName = NormPath(Item.BinaryFile)\r
419                         FileType = Item.FileType\r
420                         Target = Item.Target\r
421                         FeatureFlag = Item.FeatureFlag\r
422                         pb.Binaries.append(ModuleBinaryFileClass(FileName, FileType, Target, FeatureFlag))\r
423 \r
424                 #Sources\r
425                 for Item in Module.Sources:\r
426                     if Arch in Item.SupArchList:\r
427                         SourceFile = NormPath(Item.SourceFile)\r
428                         TagName = Item.TagName\r
429                         ToolCode = Item.ToolCode\r
430                         ToolChainFamily = Item.ToolChainFamily\r
431                         FeatureFlag = Item.FeatureFlag\r
432                         pb.Sources.append(ModuleSourceFileClass(SourceFile, TagName, ToolCode, ToolChainFamily, FeatureFlag))\r
433 \r
434                 # Protocols\r
435                 for Item in Module.Protocols:\r
436                     if Arch in Item.SupArchList:\r
437                         pb.Protocols.append(Item.CName)\r
438 \r
439                 # Ppis\r
440                 for Item in Module.Ppis:\r
441                     if Arch in Item.SupArchList:\r
442                         pb.Ppis.append(Item.CName)\r
443 \r
444                 # Guids\r
445                 for Item in Module.Guids:\r
446                     if Arch in Item.SupArchList:\r
447                         pb.Ppis.append(Item.CName)\r
448 \r
449                 # Includes\r
450                 for Item in Module.Includes:\r
451                     if Arch in Item.SupArchList:\r
452                         pb.Includes.append(NormPath(Item.FilePath))\r
453 \r
454                 # Packages\r
455                 for Item in Module.PackageDependencies:\r
456                     if Arch in Item.SupArchList:\r
457                         pb.Packages.append(NormPath(Item.FilePath))\r
458 \r
459                 # BuildOptions\r
460                 for Item in Module.BuildOptions:\r
461                     if Arch in Item.SupArchList:\r
462                         pb.BuildOptions[(Item.ToolChainFamily, Item.ToolChain)] = Item.Option\r
463                 self.FindBuildOptions(Arch, Inf, pb.BuildOptions)\r
464 \r
465                 # Depex\r
466                 for Item in Module.Depex:\r
467                     if Arch in Item.SupArchList:\r
468                         pb.Depex = pb.Depex + Item.Depex + ' '\r
469                 pb.Depex = pb.Depex.strip()\r
470 \r
471                 # LibraryClasses\r
472                 for Item in Module.LibraryClasses:\r
473                     if Arch in Item.SupArchList:\r
474                         Lib = Item.LibraryClass\r
475                         RecommendedInstance = Item.RecommendedInstance\r
476                         if pb.LibraryClass != []:\r
477                             # For Library\r
478                             for Libs in pb.LibraryClass:\r
479                                 for Type in Libs.SupModList:\r
480                                     Instance = self.FindLibraryClassInstanceOfLibrary(Lib, Arch, Type)\r
481                                     if Instance == None:\r
482                                         Instance = RecommendedInstance\r
483                                     pb.LibraryClasses[(Lib, Type)] = NormPath(Instance)\r
484                         else:\r
485                             # For Module\r
486                             Instance = self.FindLibraryClassInstanceOfModule(Lib, Arch, pb.ModuleType, Inf)\r
487                             if Instance == None:\r
488                                 Instance = RecommendedInstance\r
489                             pb.LibraryClasses[(Lib, pb.ModuleType)] = NormPath(Instance)\r
490 \r
491                 # Pcds\r
492                 for Item in Module.PcdCodes:\r
493                     if Arch in Item.SupArchList:\r
494                         Name = Item.CName\r
495                         Guid = Item.TokenSpaceGuidCName\r
496                         Type = Item.ItemType\r
497                         pb.Pcds[(Name, Guid)] = self.FindPcd(Arch, Inf, Name, Guid, Type, PcdsSet)\r
498 \r
499                 # Add to database\r
500                 self.Build[Arch].ModuleDatabase[Inf] = pb\r
501                 pb = None\r
502 \r
503     #\r
504     # Update Libraries Of Platform Database\r
505     #\r
506     def UpdateLibrariesOfPlatform(self):\r
507         for Arch in self.SupArchList:\r
508             PlatformDatabase = self.Build[Arch].PlatformDatabase\r
509             for Dsc in PlatformDatabase:\r
510                 Platform = PlatformDatabase[Dsc]\r
511                 for Inf in Platform.Modules:\r
512                     if not self.IsModuleDefinedInPlatform(Inf, Arch):\r
513                         continue\r
514                     Module = self.Build[Arch].ModuleDatabase[NormPath(Inf)]\r
515                     if Module.LibraryClass == None or Module.LibraryClass == []:\r
516                         self.UpdateLibrariesOfModule(Module, Arch)\r
517                         for Key in Module.LibraryClasses:\r
518                             Lib = Module.LibraryClasses[Key]\r
519                             if Lib not in Platform.Libraries:\r
520                                 Platform.Libraries.append(Lib)\r
521 ##                    Stack = [NormPath(str(Module))]\r
522 ##                    Libs = []\r
523 ##                    while len(Stack) > 0:\r
524 ##                        M = self.Build[Arch].ModuleDatabase[Stack.pop()]\r
525 ##                        for Key, Lib in M.LibraryClasses.iteritems():\r
526 ##                            if Module.ModuleType not in Key or Lib == None or Lib == "":\r
527 ##                                continue\r
528 ##                            Lib = NormPath(Lib)\r
529 ##                            if Lib not in Platform.Libraries:\r
530 ##                                Platform.Libraries.append(Lib)\r
531 ##                            if Lib not in Libs:\r
532 ##                                Libs.append(Lib)\r
533 ##                                Stack.append(Lib)\r
534 \r
535     def UpdateLibrariesOfModule(self, Module, Arch):\r
536         ModuleDatabase = self.Build[Arch].ModuleDatabase\r
537 \r
538         ModuleType = Module.ModuleType\r
539         LibraryConsumerList = [Module]\r
540 \r
541         Constructor         = []\r
542         ConsumedByList      = {}\r
543         LibraryInstance     = {}\r
544 \r
545         EdkLogger.verbose("")\r
546         EdkLogger.verbose("Library instances of module [%s]:" % str(Module))\r
547         while len(LibraryConsumerList) > 0:\r
548             module = LibraryConsumerList.pop()\r
549             for Key, LibraryPath in module.LibraryClasses.iteritems():\r
550                 # The "Key" is in format of (library_class_name, supported_module_type)\r
551                 LibraryClassName = Key[0]\r
552                 if ModuleType != "USER_DEFINED" and ModuleType not in Key:\r
553                     EdkLogger.debug(EdkLogger.DEBUG_3, "%s for module type %s is not supported (%s)" % (Key + (LibraryPath,)))\r
554                     continue\r
555                 if LibraryPath == None or LibraryPath == "":\r
556                     EdkLogger.warn("\tWARNING: Library instance for library class %s is not found" % LibraryClassName)\r
557                     continue\r
558 \r
559                 LibraryModule = ModuleDatabase[LibraryPath]\r
560                 if LibraryClassName not in LibraryInstance:\r
561                     LibraryConsumerList.append(LibraryModule)\r
562                     LibraryInstance[LibraryClassName] = LibraryModule\r
563                     EdkLogger.verbose("\t" + LibraryClassName + " : " + str(LibraryModule))\r
564 \r
565                 if LibraryModule.ConstructorList != [] and LibraryModule not in Constructor:\r
566                     Constructor.append(LibraryModule)\r
567 \r
568                 if LibraryModule not in ConsumedByList:\r
569                     ConsumedByList[LibraryModule] = []\r
570                 if module != Module:\r
571                     if module in ConsumedByList[LibraryModule]:\r
572                         continue\r
573                     ConsumedByList[LibraryModule].append(module)\r
574         #\r
575         # Initialize the sorted output list to the empty set\r
576         #\r
577         SortedLibraryList = []\r
578         #\r
579         # Q <- Set of all nodes with no incoming edges\r
580         #\r
581         LibraryList = LibraryInstance.values()\r
582         Q = []\r
583         for m in LibraryList:\r
584             #\r
585             # check if there're duplicate library classes\r
586             #\r
587             for Lc in m.LibraryClass:\r
588                 if Lc.LibraryClass in LibraryInstance and str(m) != str(LibraryInstance[Lc.LibraryClass]):\r
589                     raise AutoGenError(msg="More than one library instance found for library class %s in module %s:\n\t%s\n\t%s"\r
590                                            % (Lc.LibraryClass, Module, LibraryInstance[Lc.LibraryClass], str(m)))\r
591             if ConsumedByList[m] == []:\r
592                 Q.insert(0, m)\r
593         #\r
594         # while Q is not empty do\r
595         #\r
596         while Q != []:\r
597             #\r
598             # remove node n from Q\r
599             #\r
600             n = Q.pop()\r
601             #\r
602             # output n\r
603             #\r
604             SortedLibraryList.append(n)\r
605             #\r
606             # for each node m with an edge e from n to m do\r
607             #\r
608             for m in LibraryList:\r
609                 if n not in ConsumedByList[m]:\r
610                     continue\r
611                 #\r
612                 # remove edge e from the graph\r
613                 #\r
614                 ConsumedByList[m].remove(n)\r
615                 #\r
616                 # If m has no other incoming edges then\r
617                 #\r
618                 if ConsumedByList[m] == []:\r
619                     #\r
620                     # insert m into Q\r
621                     #\r
622                     Q.insert(0,m)\r
623 \r
624             EdgeRemoved = True\r
625             while Q == [] and EdgeRemoved:\r
626                 EdgeRemoved = False\r
627                 #\r
628                 # for each node m with a Constructor\r
629                 #\r
630                 for m in LibraryList:\r
631                     if m in Constructor:\r
632                         #\r
633                         # for each node n without a constructor with an edge e from m to n\r
634                         #\r
635                         for n in ConsumedByList[m]:\r
636                             if n not in Constructor:\r
637                                 #\r
638                                 # remove edge e from the graph\r
639                                 #\r
640                                 ConsumedByList[m].remove(n)\r
641                                 EdgeRemoved = True\r
642                                 if ConsumedByList[m] == []:\r
643                                     #\r
644                                     # insert m into Q\r
645                                     #\r
646                                     Q.insert(0,m)\r
647                                     break\r
648                     if Q != []:\r
649                         break\r
650 \r
651         #\r
652         # if any remaining node m in the graph has a constructor and an incoming edge, then the graph has a cycle\r
653         #\r
654         for m in LibraryList:\r
655             if ConsumedByList[m] != [] and m in Constructor:\r
656                 errorMessage = 'Library [%s] with constructors has a cycle:' % str(m)\r
657                 errorMessage += "\n\tconsumed by " + "\n\tconsumed by ".join([str(l) for l in ConsumedByList[m]])\r
658                 raise AutoGenError(msg=errorMessage)\r
659             if m not in SortedLibraryList:\r
660                 SortedLibraryList.append(m)\r
661 \r
662         #\r
663         # Build the list of constructor and destructir names\r
664         # The DAG Topo sort produces the destructor order, so the list of constructors must generated in the reverse order\r
665         #\r
666         SortedLibraryList.reverse()\r
667         Module.LibraryClasses = sdict()\r
668         for L in SortedLibraryList:\r
669             for Lc in L.LibraryClass:\r
670                 Module.LibraryClasses[Lc.LibraryClass, ModuleType] = str(L)\r
671             #\r
672             # Merge PCDs from library instance\r
673             #\r
674             for Key in L.Pcds:\r
675                 if Key not in Module.Pcds:\r
676                     Module.Pcds[Key] = L.Pcds[Key]\r
677             #\r
678             # Merge GUIDs from library instance\r
679             #\r
680             for CName in L.Guids:\r
681                 if CName not in Module.Guids:\r
682                     Module.Guids.append(CName)\r
683             #\r
684             # Merge Protocols from library instance\r
685             #\r
686             for CName in L.Protocols:\r
687                 if CName not in Module.Protocols:\r
688                     Module.Protocols.append(CName)\r
689             #\r
690             # Merge Ppis from library instance\r
691             #\r
692             for CName in L.Ppis:\r
693                 if CName not in Module.Ppis:\r
694                     Module.Ppis.append(CName)\r
695 \r
696     #\r
697     # Generate build database for all arches\r
698     #\r
699     def GenBuildDatabase(self, PcdsSet = {}):\r
700         self.GenPlatformDatabase()\r
701         self.GenPackageDatabase()\r
702         self.GenModuleDatabase(PcdsSet)\r
703         self.UpdateLibrariesOfPlatform()\r
704 \r
705     #\r
706     # Return a full path with workspace dir\r
707     #\r
708     def WorkspaceFile(self, Filename):\r
709         return WorkspaceFile(self.WorkspaceDir, Filename)\r
710 \r
711     #\r
712     # If a module of a platform has its own override libraryclass but the libraryclass not defined in the module\r
713     # Add this libraryclass to the module\r
714     #\r
715     def UpdateLibraryClassOfModule(self, InfFileName, LibraryClass, Arch, InstanceFilePath):\r
716         #\r
717         # Update the library instance itself to add this libraryclass name\r
718         #\r
719         LibList = self.InfDatabase[NormPath(InstanceFilePath)].Module.Header.LibraryClass\r
720         NotFound = True\r
721         for Lib in LibList:\r
722             #\r
723             # Find this LibraryClass\r
724             #\r
725             if Lib.LibraryClass == LibraryClass:\r
726                 NotFound = False;\r
727                 break;\r
728         if NotFound:\r
729             NewLib = LibraryClassClass()\r
730             NewLib.LibraryClass = LibraryClass\r
731             NewLib.SupModuleList = self.InfDatabase[NormPath(InstanceFilePath)].Module.Header.ModuleType.split()\r
732             self.InfDatabase[NormPath(InstanceFilePath)].Module.Header.LibraryClass.append(NewLib)\r
733 \r
734         #\r
735         # Add it to LibraryClasses Section for the module which is using the library\r
736         #\r
737         LibList = self.InfDatabase[NormPath(InfFileName)].Module.LibraryClasses\r
738         NotFound = True\r
739         for Lib in LibList:\r
740             #\r
741             # Find this LibraryClass\r
742             #\r
743             if Lib.LibraryClass == LibraryClass:\r
744                 if Arch in Lib.SupArchList:\r
745                     return\r
746                 else:\r
747                     Lib.SupArchList.append(Arch)\r
748                     return\r
749         if NotFound:\r
750             Lib = LibraryClassClass()\r
751             Lib.LibraryClass = LibraryClass\r
752             Lib.SupArchList = [Arch]\r
753             self.InfDatabase[NormPath(InfFileName)].Module.LibraryClasses.append(Lib)\r
754 \r
755     #\r
756     # Create a Inf instance for input inf file and add it to InfDatabase\r
757     #\r
758     def AddToInfDatabase(self, InfFileName):\r
759         InfFileName = NormPath(InfFileName)\r
760         File = self.WorkspaceFile(InfFileName)\r
761         if os.path.exists(File) and os.path.isfile(File):\r
762             if InfFileName not in self.InfDatabase:\r
763                 self.InfDatabase[InfFileName] = Inf(File, True, True, self.WorkspaceDir)\r
764         else:\r
765             raise ParserError(FILE_NOT_FOUND, name = File)\r
766 \r
767     #\r
768     # Create a Dec instance for input dec file and add it to DecDatabase\r
769     #\r
770     def AddToDecDatabase(self, DecFileName):\r
771         DecFileName = NormPath(DecFileName)\r
772         File = self.WorkspaceFile(DecFileName)\r
773         if os.path.exists(File) and os.path.isfile(File):\r
774             if DecFileName not in self.DecDatabase:\r
775                 self.DecDatabase[DecFileName] = Dec(File, True, True, self.WorkspaceDir)\r
776         else:\r
777             raise ParserError(FILE_NOT_FOUND, name = File)\r
778 \r
779     #\r
780     # Search PlatformBuildDatabase to find LibraryClass Instance for Module\r
781     # Return the instance if found\r
782     #\r
783     def FindLibraryClassInstanceOfModule(self, Lib, Arch, ModuleType, ModuleName):\r
784         #\r
785         # First find if exist in <LibraryClass> of <Components> from dsc file\r
786         #\r
787         for Dsc in self.DscDatabase.keys():\r
788             Platform = self.DscDatabase[Dsc].Platform\r
789             for Module in Platform.Modules.ModuleList:\r
790                 if Arch in Module.SupArchList:\r
791                     if NormPath(Module.FilePath) == ModuleName:\r
792                         for LibraryClass in Module.LibraryClasses.LibraryList:\r
793                             if LibraryClass.Name == Lib:\r
794                                 return NormPath(LibraryClass.FilePath)\r
795         #\r
796         #Second find if exist in <LibraryClass> of <LibraryClasses> from dsc file\r
797         #\r
798         return self.FindLibraryClassInstanceOfLibrary(Lib, Arch, ModuleType)\r
799 \r
800     #\r
801     # Search PlatformBuildDatabase to find LibraryClass Instance for Library\r
802     # Return the instance if found\r
803     #\r
804     def FindLibraryClassInstanceOfLibrary(self, Lib, Arch, Type):\r
805         for Dsc in self.DscDatabase.keys():\r
806             Platform  = self.DscDatabase[Dsc].Platform\r
807             if (Lib, Type) in self.Build[Arch].PlatformDatabase[Dsc].LibraryClasses:\r
808                 return self.Build[Arch].PlatformDatabase[Dsc].LibraryClasses[(Lib, Type)]\r
809             elif (Lib, '') in self.Build[Arch].PlatformDatabase[Dsc].LibraryClasses:\r
810                 return self.Build[Arch].PlatformDatabase[Dsc].LibraryClasses[(Lib, '')]\r
811         return None\r
812 \r
813     #\r
814     # Search DscDatabase to find component definition of ModuleName\r
815     # Override BuildOption if it is defined in component\r
816     #\r
817     def FindBuildOptions(self, Arch, ModuleName, BuildOptions):\r
818         for Dsc in self.DscDatabase.keys():\r
819             #\r
820             # First find if exist in <BuildOptions> of <Components> from dsc file\r
821             # if find, use that override the one defined in inf file\r
822             #\r
823             Platform = self.DscDatabase[Dsc].Platform\r
824             for Module in Platform.Modules.ModuleList:\r
825                 if Arch in Module.SupArchList:\r
826                     if NormPath(Module.FilePath) == ModuleName:\r
827                         for BuildOption in Module.ModuleSaBuildOption.BuildOptionList:\r
828                             BuildOptions[(BuildOption.ToolChainFamily, BuildOption.ToolChain)] = BuildOption.Option\r
829 \r
830     #\r
831     # Search platform database, package database, module database and PcdsSet from Fdf\r
832     # Return found Pcd\r
833     #\r
834     def FindPcd(self, Arch, ModuleName, Name, Guid, Type, PcdsSet):\r
835         DatumType = ''\r
836         Value = ''\r
837         Token = ''\r
838         MaxDatumSize = ''\r
839         SkuInfoList = {}\r
840         IsOverrided = False\r
841         IsFoundInDsc = False\r
842         IsFoundInDec = False\r
843         #\r
844         # First get information from platform database\r
845         #\r
846         for Dsc in self.Build[Arch].PlatformDatabase.keys():\r
847             Pcds = self.Build[Arch].PlatformDatabase[Dsc].Pcds\r
848             if (Name, Guid) in Pcds:\r
849                 Type = Pcds[(Name, Guid)].Type\r
850                 DatumType = Pcds[(Name, Guid)].DatumType\r
851                 Value = Pcds[(Name, Guid)].DefaultValue\r
852                 Token = Pcds[(Name, Guid)].TokenValue\r
853                 MaxDatumSize = Pcds[(Name, Guid)].MaxDatumSize\r
854                 SkuInfoList =  Pcds[(Name, Guid)].SkuInfoList\r
855                 IsOverrided = True\r
856                 IsFoundInDsc = True\r
857                 break\r
858 \r
859         #\r
860         # Second get information from package database\r
861         #\r
862         for Dec in self.Build[Arch].PackageDatabase.keys():\r
863             Pcds = self.Build[Arch].PackageDatabase[Dec].Pcds\r
864             if (Name, Guid) in Pcds:\r
865                 DatumType = Pcds[(Name, Guid)].DatumType\r
866                 Token = Pcds[(Name, Guid)].TokenValue\r
867                 IsOverrided = True\r
868                 IsFoundInDec = True\r
869                 break\r
870         if not IsFoundInDec:\r
871             ErrorMsg = "Pcd '%s' defined in module '%s' is not found in any package" % (Name, ModuleName)\r
872             raise ParserError(PARSER_ERROR, msg = ErrorMsg)\r
873 \r
874         #\r
875         # Third get information from <Pcd> of <Compontents> from module database\r
876         #\r
877         for Dsc in self.DscDatabase.keys():\r
878             for Module in self.DscDatabase[Dsc].Platform.Modules.ModuleList:\r
879                 if Arch in Module.SupArchList:\r
880                     if NormPath(Module.FilePath) == ModuleName:\r
881                         for Pcd in Module.PcdBuildDefinitions:\r
882                             if (Name, Guid) == (Pcd.CName, Pcd.TokenSpaceGuidCName):\r
883                                 if Pcd.DefaultValue != '':\r
884                                     Value = Pcd.DefaultValue\r
885                                 if Pcd.MaxDatumSize != '':\r
886                                     MaxDatumSize = Pcd.MaxDatumSize\r
887                                 IsFoundInDsc = True\r
888                                 IsOverrided = True\r
889                                 break\r
890 \r
891         #\r
892         # Last get information from PcdsSet defined by FDF\r
893         #\r
894         if (Name, Guid) in PcdsSet:\r
895             Value = PcdsSet[(Name, Guid)]\r
896             IsFoundInDsc = True\r
897             IsOverrided = True\r
898 \r
899         #\r
900         # Not found in any platform and fdf\r
901         #\r
902         if not IsFoundInDsc:\r
903             ErrorMsg = "Pcd '%s' defined in module '%s' is not found in any platform" % (Name, ModuleName)\r
904             raise ParserError(PARSER_ERROR, msg = ErrorMsg)\r
905 \r
906         return PcdClassObject(Name, Guid, Type, DatumType, Value, Token, MaxDatumSize, SkuInfoList, IsOverrided)\r
907 \r
908     #\r
909     # Search in InfDatabase, find the supmodulelist of the libraryclass\r
910     #\r
911     def FindSupModuleListOfLibraryClass(self, LibraryClass, OverridedLibraryClassList):\r
912         Name = LibraryClass.Name\r
913         FilePath = NormPath(LibraryClass.FilePath)\r
914         SupModuleList = copy.copy(LibraryClass.SupModuleList)\r
915 \r
916         #\r
917         # If the SupModuleList means all, remove overrided module types of platform\r
918         #\r
919         if SupModuleList == DataType.SUP_MODULE_LIST:\r
920             EdkLogger.debug(EdkLogger.DEBUG_3, "\tLibraryClass %s supports all module types" % Name)\r
921             for Item in OverridedLibraryClassList:\r
922                 #\r
923                 # Find a library class with the same name\r
924                 #\r
925                 if Item.Name == Name:\r
926                     #\r
927                     # Do nothing if it is itself\r
928                     #\r
929                     if Item.SupModuleList == DataType.SUP_MODULE_LIST:\r
930                         continue\r
931                     #\r
932                     # If not itself, check arch first\r
933                     #\r
934                     for Arch in LibraryClass.SupArchList:\r
935                         #\r
936                         # If arch is supportted, remove all related module type\r
937                         #\r
938                         if Arch in Item.SupArchList:\r
939                             for ModuleType in Item.SupModuleList:\r
940                                 EdkLogger.debug(EdkLogger.DEBUG_3, "\tLibraryClass %s has specific defined module types" % Name)\r
941                                 if ModuleType in SupModuleList:\r
942                                     SupModuleList.remove(ModuleType)\r
943 \r
944         return SupModuleList\r
945 \r
946     #\r
947     # Check if the module is defined in <Compentent> of <Platform>\r
948     #\r
949     def IsModuleDefinedInPlatform(self, Inf, Arch):\r
950         Inf = NormPath(Inf)\r
951         for Dsc in self.DscDatabase.values():\r
952             for LibraryClass in Dsc.Platform.LibraryClasses.LibraryList:\r
953                 if Inf == NormPath(LibraryClass.FilePath) and Arch in LibraryClass.SupArchList:\r
954                     return True\r
955             for Module in Dsc.Platform.Modules.ModuleList:\r
956                 if Inf == NormPath(Module.FilePath) and Arch in Module.SupArchList:\r
957                     return True\r
958                 for Item in Module.LibraryClasses.LibraryList:\r
959                     if Inf == NormPath(Item.FilePath):\r
960                         return True\r
961 \r
962         return False\r
963 \r
964     #\r
965     # Show all content of the workspacebuild\r
966     #\r
967     def ShowWorkspaceBuild(self):\r
968         print ewb.DscDatabase\r
969         print ewb.InfDatabase\r
970         print ewb.DecDatabase\r
971         print 'SupArchList', ewb.SupArchList\r
972         print 'BuildTarget', ewb.BuildTarget\r
973         print 'SkuId', ewb.SkuId\r
974 \r
975         for arch in ewb.SupArchList:\r
976             print arch\r
977             print 'Platform'\r
978             for platform in ewb.Build[arch].PlatformDatabase.keys():\r
979                 p = ewb.Build[arch].PlatformDatabase[platform]\r
980                 print 'DescFilePath = ', p.DescFilePath\r
981                 print 'PlatformName = ', p.PlatformName\r
982                 print 'Guid = ', p.Guid\r
983                 print 'Version = ', p.Version\r
984                 print 'OutputDirectory = ', p.OutputDirectory\r
985                 print 'FlashDefinition = ', p.FlashDefinition\r
986                 print 'SkuIds = ', p.SkuIds\r
987                 print 'Modules = ', p.Modules\r
988                 print 'LibraryClasses = ', p.LibraryClasses\r
989                 print 'Pcds = ', p.Pcds\r
990                 for item in p.Pcds.keys():\r
991                     print p.Pcds[item]\r
992                 print 'BuildOptions = ', p.BuildOptions\r
993                 print ''\r
994             # End of Platform\r
995 \r
996             print 'package'\r
997             for package in ewb.Build[arch].PackageDatabase.keys():\r
998                 p = ewb.Build[arch].PackageDatabase[package]\r
999                 print 'DescFilePath = ', p.DescFilePath\r
1000                 print 'PackageName = ', p.PackageName\r
1001                 print 'Guid = ', p.Guid\r
1002                 print 'Version = ', p.Version\r
1003                 print 'Protocols = ', p.Protocols\r
1004                 print 'Ppis = ', p.Ppis\r
1005                 print 'Guids = ', p.Guids\r
1006                 print 'Includes = ', p.Includes\r
1007                 print 'LibraryClasses = ', p.LibraryClasses\r
1008                 print 'Pcds = ', p.Pcds\r
1009                 for item in p.Pcds.keys():\r
1010                     print p.Pcds[item]\r
1011                 print ''\r
1012             # End of Package\r
1013 \r
1014             print 'module'\r
1015             for module in ewb.Build[arch].ModuleDatabase.keys():\r
1016                 p = ewb.Build[arch].ModuleDatabase[module]\r
1017                 print 'DescFilePath = ', p.DescFilePath\r
1018                 print 'BaseName = ', p.BaseName\r
1019                 print 'ModuleType = ', p.ModuleType\r
1020                 print 'Guid = ', p.Guid\r
1021                 print 'Version = ', p.Version\r
1022                 print 'CustomMakefile = ', p.CustomMakefile\r
1023                 print 'Specification = ', p.Specification\r
1024                 print 'PcdIsDriver = ', p.PcdIsDriver\r
1025                 for Lib in p.LibraryClass:\r
1026                     print 'LibraryClassDefinition = ', Lib.LibraryClass, 'SupModList = ', Lib.SupModList\r
1027                 print 'ModuleEntryPointList = ', p.ModuleEntryPointList\r
1028                 print 'ModuleUnloadImageList = ', p.ModuleUnloadImageList\r
1029                 print 'ConstructorList = ', p.ConstructorList\r
1030                 print 'DestructorList = ', p.DestructorList\r
1031 \r
1032                 print 'Binaries = '\r
1033                 for item in p.Binaries:\r
1034                     print item.BinaryFile, item.FeatureFlag\r
1035                 print 'Sources = '\r
1036                 for item in p.Sources:\r
1037                     print item.SourceFile\r
1038                 print 'LibraryClasses = ', p.LibraryClasses\r
1039                 print 'Protocols = ', p.Protocols\r
1040                 print 'Ppis = ', p.Ppis\r
1041                 print 'Guids = ', p.Guids\r
1042                 print 'Includes = ', p.Includes\r
1043                 print 'Packages = ', p.Packages\r
1044                 print 'Pcds = ', p.Pcds\r
1045                 for item in p.Pcds.keys():\r
1046                     print p.Pcds[item]\r
1047                 print 'BuildOptions = ', p.BuildOptions\r
1048                 print 'Depex = ', p.Depex\r
1049                 print ''\r
1050             # End of Module\r
1051 \r
1052 #\r
1053 # This acts like the main() function for the script, unless it is 'import'ed into another\r
1054 # script.\r
1055 #\r
1056 if __name__ == '__main__':\r
1057     # Nothing to do here. Could do some unit tests.\r
1058     w = os.getenv('WORKSPACE')\r
1059     ewb = WorkspaceBuild('Nt32Pkg/Nt32Pkg.dsc', w)\r
1060     ewb.GenBuildDatabase({('PcdDevicePathSupportDevicePathFromText, gEfiMdeModulePkgTokenSpaceGuid') : 'KKKKKKKKKKKKKKKKKKKKK'})\r
1061     ewb.ShowWorkspaceBuild()\r