]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/Workspace/WorkspaceDatabase.py
BaseTools: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / BaseTools / Source / Python / Workspace / WorkspaceDatabase.py
1 ## @file
2 # This file is used to create a database used by build tool
3 #
4 # Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
5 # (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
6 # SPDX-License-Identifier: BSD-2-Clause-Patent
7 #
8
9 ##
10 # Import Modules
11 #
12 from __future__ import absolute_import
13 from Common.StringUtils import *
14 from Common.DataType import *
15 from Common.Misc import *
16 from types import *
17
18 from .MetaDataTable import *
19 from .MetaFileTable import *
20 from .MetaFileParser import *
21
22 from Workspace.DecBuildData import DecBuildData
23 from Workspace.DscBuildData import DscBuildData
24 from Workspace.InfBuildData import InfBuildData
25
26 ## Database
27 #
28 # This class defined the build database for all modules, packages and platform.
29 # It will call corresponding parser for the given file if it cannot find it in
30 # the database.
31 #
32 # @param DbPath Path of database file
33 # @param GlobalMacros Global macros used for replacement during file parsing
34 # @param RenewDb=False Create new database file if it's already there
35 #
36 class WorkspaceDatabase(object):
37
38 #
39 # internal class used for call corresponding file parser and caching the result
40 # to avoid unnecessary re-parsing
41 #
42 class BuildObjectFactory(object):
43
44 _FILE_TYPE_ = {
45 ".inf" : MODEL_FILE_INF,
46 ".dec" : MODEL_FILE_DEC,
47 ".dsc" : MODEL_FILE_DSC,
48 }
49
50 # file parser
51 _FILE_PARSER_ = {
52 MODEL_FILE_INF : InfParser,
53 MODEL_FILE_DEC : DecParser,
54 MODEL_FILE_DSC : DscParser,
55 }
56
57 # convert to xxxBuildData object
58 _GENERATOR_ = {
59 MODEL_FILE_INF : InfBuildData,
60 MODEL_FILE_DEC : DecBuildData,
61 MODEL_FILE_DSC : DscBuildData,
62 }
63
64 _CACHE_ = {} # (FilePath, Arch) : <object>
65
66 # constructor
67 def __init__(self, WorkspaceDb):
68 self.WorkspaceDb = WorkspaceDb
69
70 # key = (FilePath, Arch=None)
71 def __contains__(self, Key):
72 FilePath = Key[0]
73 if len(Key) > 1:
74 Arch = Key[1]
75 else:
76 Arch = None
77 return (FilePath, Arch) in self._CACHE_
78
79 # key = (FilePath, Arch=None, Target=None, Toolchain=None)
80 def __getitem__(self, Key):
81 FilePath = Key[0]
82 KeyLength = len(Key)
83 if KeyLength > 1:
84 Arch = Key[1]
85 else:
86 Arch = None
87 if KeyLength > 2:
88 Target = Key[2]
89 else:
90 Target = None
91 if KeyLength > 3:
92 Toolchain = Key[3]
93 else:
94 Toolchain = None
95
96 # if it's generated before, just return the cached one
97 Key = (FilePath, Arch, Target, Toolchain)
98 if Key in self._CACHE_:
99 return self._CACHE_[Key]
100
101 # check file type
102 BuildObject = self.CreateBuildObject(FilePath, Arch, Target, Toolchain)
103 self._CACHE_[Key] = BuildObject
104 return BuildObject
105 def CreateBuildObject(self,FilePath, Arch, Target, Toolchain):
106 Ext = FilePath.Type
107 if Ext not in self._FILE_TYPE_:
108 return None
109 FileType = self._FILE_TYPE_[Ext]
110 if FileType not in self._GENERATOR_:
111 return None
112
113 # get the parser ready for this file
114 MetaFile = self._FILE_PARSER_[FileType](
115 FilePath,
116 FileType,
117 Arch,
118 MetaFileStorage(self.WorkspaceDb, FilePath, FileType)
119 )
120 # always do post-process, in case of macros change
121 MetaFile.DoPostProcess()
122 # object the build is based on
123 BuildObject = self._GENERATOR_[FileType](
124 FilePath,
125 MetaFile,
126 self,
127 Arch,
128 Target,
129 Toolchain
130 )
131 return BuildObject
132
133 # placeholder for file format conversion
134 class TransformObjectFactory:
135 def __init__(self, WorkspaceDb):
136 self.WorkspaceDb = WorkspaceDb
137
138 # key = FilePath, Arch
139 def __getitem__(self, Key):
140 pass
141
142 ## Constructor of WorkspaceDatabase
143 #
144 # @param DbPath Path of database file
145 # @param GlobalMacros Global macros used for replacement during file parsing
146 # @param RenewDb=False Create new database file if it's already there
147 #
148 def __init__(self):
149 self.DB = dict()
150 # create table for internal uses
151 self.TblDataModel = DataClass.MODEL_LIST
152 self.TblFile = []
153 self.Platform = None
154
155 # conversion object for build or file format conversion purpose
156 self.BuildObject = WorkspaceDatabase.BuildObjectFactory(self)
157 self.TransformObject = WorkspaceDatabase.TransformObjectFactory(self)
158
159 def SetFileTimeStamp(self,FileId,TimeStamp):
160 self.TblFile[FileId-1][6] = TimeStamp
161
162 def GetFileTimeStamp(self,FileId):
163 return self.TblFile[FileId-1][6]
164
165
166 ## Summarize all packages in the database
167 def GetPackageList(self, Platform, Arch, TargetName, ToolChainTag):
168 self.Platform = Platform
169 PackageList = []
170 Pa = self.BuildObject[self.Platform, Arch, TargetName, ToolChainTag]
171 #
172 # Get Package related to Modules
173 #
174 for Module in Pa.Modules:
175 ModuleObj = self.BuildObject[Module, Arch, TargetName, ToolChainTag]
176 for Package in ModuleObj.Packages:
177 if Package not in PackageList:
178 PackageList.append(Package)
179 #
180 # Get Packages related to Libraries
181 #
182 for Lib in Pa.LibraryInstances:
183 LibObj = self.BuildObject[Lib, Arch, TargetName, ToolChainTag]
184 for Package in LibObj.Packages:
185 if Package not in PackageList:
186 PackageList.append(Package)
187
188 return PackageList
189
190 ## Summarize all platforms in the database
191 def PlatformList(self):
192 RetVal = []
193 for PlatformFile in [item[3] for item in self.TblFile if item[5] == MODEL_FILE_DSC]:
194 try:
195 RetVal.append(self.BuildObject[PathClass(PlatformFile), TAB_COMMON])
196 except:
197 pass
198 return RetVal
199
200 def MapPlatform(self, Dscfile):
201 Platform = self.BuildObject[PathClass(Dscfile), TAB_COMMON]
202 if Platform is None:
203 EdkLogger.error('build', PARSER_ERROR, "Failed to parser DSC file: %s" % Dscfile)
204 return Platform
205
206 ##
207 #
208 # This acts like the main() function for the script, unless it is 'import'ed into another
209 # script.
210 #
211 if __name__ == '__main__':
212 pass
213