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