]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/msa2inf/EdkIIWorkspaceGuidsInfo.py
Sync EDKII BaseTools to BaseTools project r1971
[mirror_edk2.git] / BaseTools / Source / Python / msa2inf / EdkIIWorkspaceGuidsInfo.py
CommitLineData
30fdf114
LG
1## @file\r
2# Collects the Guid Information in current workspace.\r
3#\r
40d841f6
LG
4# Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>\r
5# This program and the accompanying materials\r
30fdf114
LG
6# are licensed and made available under the terms and conditions of the BSD License\r
7# which accompanies this distribution. The full text of the license may be found at\r
8# http://opensource.org/licenses/bsd-license.php\r
9#\r
10# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12#\r
13\r
14##\r
15# Import Modules\r
16#\r
17import os\r
18import fnmatch\r
19from Common.EdkIIWorkspace import EdkIIWorkspace\r
20from Common.MigrationUtilities import *\r
21\r
22## A class for EdkII work space to resolve Guids.\r
23#\r
24# This class inherits from EdkIIWorkspace and collects the Guids information\r
25# in current workspace. The Guids information is important to translate the\r
26# package Guids and recommended library instances Guids to relative file path\r
27# (to workspace directory) in MSA files.\r
28#\r
29class EdkIIWorkspaceGuidsInfo(EdkIIWorkspace):\r
30\r
31 ## The classconstructor.\r
32 #\r
33 # The constructor initialize workspace directory. It does not collect\r
34 # pakage and module Guids info at initialization; instead, it collects them\r
35 # on the fly.\r
36 #\r
37 # @param self The object pointer.\r
38 #\r
39 def __init__(self):\r
40 # Initialize parent class.\r
41 EdkIIWorkspace.__init__(self)\r
42 # The internal map from Guid to FilePath.\r
43 self.__GuidToFilePath = {}\r
44 # The internal package directory list.\r
45 self.__PackageDirList = []\r
46 # The internal flag to indicate whether package Guids info has been\r
47 # to avoid re-collection collected.\r
48 self.__PackageGuidInitialized = False\r
49 # The internal flag to indicate whether module Guids info has been\r
50 # to avoid re-collection collected.\r
51 self.__ModuleGuidInitialized = False\r
52\r
53 ## Add Guid, Version and FilePath to Guids database.\r
54 #\r
55 # Add Guid, Version and FilePath to Guids database. It constructs a map\r
56 # table from Guid, Version to FilePath internally. If also detects possible\r
57 # Guid collision. For now, the version information is simply ignored and\r
58 # Guid value itself acts as master key.\r
59 #\r
60 # @param self The object pointer.\r
61 # @param Guid The Guid Value.\r
62 # @param Version The version information\r
63 #\r
64 # @retval True The Guid value is successfully added to map table.\r
65 # @retval False The Guid is an empty string or the map table\r
66 # already contains a same Guid.\r
67 #\r
68 def __AddGuidToFilePath(self, Guid, Version, FilePath):\r
69 if Guid == "":\r
70 EdkLogger.info("Cannot find Guid in file %s" % FilePath)\r
71 return False\r
72 #Add the Guid value to map table to ensure case insensitive comparison.\r
73 OldFilePath = self.__GuidToFilePath.setdefault(Guid.lower(), FilePath)\r
74 if OldFilePath == FilePath:\r
75 EdkLogger.verbose("File %s has new Guid '%s'" % (FilePath, Guid))\r
76 return True\r
77 else:\r
78 EdkLogger.info("File %s has duplicate Guid with & %s" % (FilePath, OldFilePath))\r
79 return False\r
80 \r
81\r
82 ## Gets file information from a module description file.\r
83 #\r
84 # Extracts Module Name, File Guid and Version number from INF, MSA and NMSA\r
85 # file. It supports to exact such information from text based INF file or\r
86 # XML based (N)MSA file.\r
87 #\r
88 # @param self The object pointer.\r
89 # @param FileName The input module file name.\r
90 #\r
91 # @retval True This module file represents a new module discovered\r
92 # in current workspace.\r
93 # @retval False This module file is not regarded as a valid module.\r
94 # The File Guid cannot be extracted or the another\r
95 # file with the same Guid already exists\r
96 #\r
97 def __GetModuleFileInfo(self, FileName):\r
98 if fnmatch.fnmatch(FileName, "*.inf"):\r
99 TagTuple = ("BASE_NAME", "FILE_GUID", "VERSION_STRING")\r
100 (Name, Guid, Version) = GetTextFileInfo(FileName, TagTuple)\r
101 else :\r
102 XmlTag1 = "ModuleSurfaceArea/MsaHeader/ModuleName"\r
103 XmlTag2 = "ModuleSurfaceArea/MsaHeader/GuidValue"\r
104 XmlTag3 = "ModuleSurfaceArea/MsaHeader/Version"\r
105 TagTuple = (XmlTag1, XmlTag2, XmlTag3)\r
106 (Name, Guid, Version) = GetXmlFileInfo(FileName, TagTuple)\r
107\r
108 return self.__AddGuidToFilePath(Guid, Version, FileName)\r
109 \r
110 \r
111 ## Gets file information from a package description file.\r
112 #\r
113 # Extracts Package Name, File Guid and Version number from INF, SPD and NSPD\r
114 # file. It supports to exact such information from text based DEC file or\r
115 # XML based (N)SPD file. EDK Compatibility Package is hardcoded to be\r
116 # ignored since no EDKII INF file depends on that package.\r
117 #\r
118 # @param self The object pointer.\r
119 # @param FileName The input package file name.\r
120 #\r
121 # @retval True This package file represents a new package\r
122 # discovered in current workspace.\r
123 # @retval False This package is not regarded as a valid package.\r
124 # The File Guid cannot be extracted or the another\r
125 # file with the same Guid already exists\r
126 #\r
127 def __GetPackageFileInfo(self, FileName):\r
128 if fnmatch.fnmatch(FileName, "*.dec"):\r
129 TagTuple = ("PACKAGE_NAME", "PACKAGE_GUID", "PACKAGE_VERSION")\r
130 (Name, Guid, Version) = GetTextFileInfo(FileName, TagTuple)\r
131 else:\r
132 XmlTag1 = "PackageSurfaceArea/SpdHeader/PackageName"\r
133 XmlTag2 = "PackageSurfaceArea/SpdHeader/GuidValue"\r
134 XmlTag3 = "PackageSurfaceArea/SpdHeader/Version"\r
135 TagTuple = (XmlTag1, XmlTag2, XmlTag3)\r
136 (Name, Guid, Version) = GetXmlFileInfo(FileName, TagTuple)\r
137 \r
138 if Name == "EdkCompatibilityPkg":\r
139 # Do not scan EDK compatibitilty package to avoid Guid collision\r
140 # with those in EDK Glue Library.\r
141 EdkLogger.verbose("Bypass EDK Compatibility Pkg")\r
142 return False\r
143 \r
144 return self.__AddGuidToFilePath(Guid, Version, FileName)\r
145\r
146 ## Iterate on all package files listed in framework database file.\r
147 #\r
148 # Yields all package description files listed in framework database files.\r
149 # The framework database file describes the packages current workspace\r
150 # includes.\r
151 #\r
152 # @param self The object pointer.\r
153 #\r
154 def __FrameworkDatabasePackageFiles(self):\r
155 XmlFrameworkDb = XmlParseFile(self.WorkspaceFile)\r
156 XmlTag = "FrameworkDatabase/PackageList/Filename"\r
157 for PackageFile in XmlElementList(XmlFrameworkDb, XmlTag):\r
158 yield os.path.join(self.WorkspaceDir, PackageFile)\r
159 \r
160 \r
161 ## Iterate on all package files in current workspace directory.\r
162 #\r
163 # Yields all package description files listed in current workspace\r
164 # directory. This happens when no framework database file exists.\r
165 #\r
166 # @param self The object pointer.\r
167 #\r
168 def __TraverseAllPackageFiles(self):\r
169 for Path, Dirs, Files in os.walk(self.WorkspaceDir):\r
170 # Ignore svn version control directory.\r
171 if ".svn" in Dirs:\r
172 Dirs.remove(".svn")\r
173 if "Build" in Dirs:\r
174 Dirs.remove("Build")\r
175 # Assume priority from high to low: DEC, NSPD, SPD.\r
176 PackageFiles = fnmatch.filter(Files, "*.dec")\r
177 if len(PackageFiles) == 0:\r
178 PackageFiles = fnmatch.filter(Files, "*.nspd")\r
179 if len(PackageFiles) == 0:\r
180 PackageFiles = fnmatch.filter(Files, "*.spd")\r
181\r
182 for File in PackageFiles:\r
183 # Assume no more package decription file in sub-directory.\r
184 del Dirs[:]\r
185 yield os.path.join(Path, File)\r
186\r
187 ## Iterate on all module files in current package directory.\r
188 #\r
189 # Yields all module description files listed in current package\r
190 # directory.\r
191 #\r
192 # @param self The object pointer.\r
193 #\r
194 def __TraverseAllModuleFiles(self):\r
195 for PackageDir in self.__PackageDirList:\r
196 for Path, Dirs, Files in os.walk(PackageDir):\r
197 # Ignore svn version control directory.\r
198 if ".svn" in Dirs:\r
199 Dirs.remove(".svn")\r
200 # Assume priority from high to low: INF, NMSA, MSA.\r
201 ModuleFiles = fnmatch.filter(Files, "*.inf")\r
202 if len(ModuleFiles) == 0:\r
203 ModuleFiles = fnmatch.filter(Files, "*.nmsa")\r
204 if len(ModuleFiles) == 0:\r
205 ModuleFiles = fnmatch.filter(Files, "*.msa")\r
206\r
207 for File in ModuleFiles:\r
208 yield os.path.join(Path, File)\r
209\r
210 ## Initialize package Guids info mapping table.\r
211 #\r
212 # Collects all package guids map to package decription file path. This\r
213 # function is invokes on demand to avoid unnecessary directory scan.\r
214 #\r
215 # @param self The object pointer.\r
216 #\r
217 def __InitializePackageGuidInfo(self):\r
218 if self.__PackageGuidInitialized:\r
219 return\r
220\r
221 EdkLogger.verbose("Start to collect Package Guids Info.")\r
222 \r
223 WorkspaceFile = os.path.join("Conf", "FrameworkDatabase.db")\r
224 self.WorkspaceFile = os.path.join(self.WorkspaceDir, WorkspaceFile)\r
225 \r
226 # Try to find the frameworkdatabase file to discover package lists\r
227 if os.path.exists(self.WorkspaceFile):\r
228 TraversePackage = self.__FrameworkDatabasePackageFiles\r
229 EdkLogger.verbose("Package list bases on: %s" % self.WorkspaceFile)\r
230 else:\r
231 TraversePackage = self.__TraverseAllPackageFiles\r
232 EdkLogger.verbose("Package list in: %s" % self.WorkspaceDir)\r
233\r
234 for FileName in TraversePackage():\r
235 if self.__GetPackageFileInfo(FileName):\r
236 PackageDir = os.path.dirname(FileName)\r
237 EdkLogger.verbose("Find new package directory %s" % PackageDir)\r
238 self.__PackageDirList.append(PackageDir)\r
239 \r
240 self.__PackageGuidInitialized = True\r
241\r
242 ## Initialize module Guids info mapping table.\r
243 #\r
244 # Collects all module guids map to module decription file path. This\r
245 # function is invokes on demand to avoid unnecessary directory scan.\r
246 #\r
247 # @param self The object pointer.\r
248 #\r
249 def __InitializeModuleGuidInfo(self):\r
250 if self.__ModuleGuidInitialized:\r
251 return\r
252 EdkLogger.verbose("Start to collect Module Guids Info")\r
253 \r
254 self.__InitializePackageGuidInfo()\r
255 for FileName in self.__TraverseAllModuleFiles():\r
256 if self.__GetModuleFileInfo(FileName):\r
257 EdkLogger.verbose("Find new module %s" % FileName)\r
258 \r
259 self.__ModuleGuidInitialized = True\r
260\r
261 ## Get Package file path by Package guid and Version.\r
262 #\r
263 # Translates the Package Guid and Version to a file path relative\r
264 # to workspace directory. If no package in current workspace match the\r
265 # input Guid, an empty file path is returned. For now, the version\r
266 # value is simply ignored.\r
267 #\r
268 # @param self The object pointer.\r
269 # @param Guid The Package Guid value to look for.\r
270 # @param Version The Package Version value to look for.\r
271 #\r
272 def ResolvePackageFilePath(self, Guid, Version = ""):\r
273 self.__InitializePackageGuidInfo()\r
274 \r
275 EdkLogger.verbose("Resolve Package Guid '%s'" % Guid)\r
276 FileName = self.__GuidToFilePath.get(Guid.lower(), "")\r
277 if FileName == "":\r
278 EdkLogger.info("Cannot resolve Package Guid '%s'" % Guid)\r
279 else:\r
280 FileName = self.WorkspaceRelativePath(FileName)\r
281 FileName = os.path.splitext(FileName)[0] + ".dec"\r
282 FileName = FileName.replace("\\", "/")\r
283 return FileName\r
284\r
285 ## Get Module file path by Package guid and Version.\r
286 #\r
287 # Translates the Module Guid and Version to a file path relative\r
288 # to workspace directory. If no module in current workspace match the\r
289 # input Guid, an empty file path is returned. For now, the version\r
290 # value is simply ignored.\r
291 #\r
292 # @param self The object pointer.\r
293 # @param Guid The Module Guid value to look for.\r
294 # @param Version The Module Version value to look for.\r
295 #\r
296 def ResolveModuleFilePath(self, Guid, Version = ""):\r
297 self.__InitializeModuleGuidInfo()\r
298 \r
299 EdkLogger.verbose("Resolve Module Guid '%s'" % Guid)\r
300 FileName = self.__GuidToFilePath.get(Guid.lower(), "")\r
301 if FileName == "":\r
302 EdkLogger.info("Cannot resolve Module Guid '%s'" % Guid)\r
303 else:\r
304 FileName = self.WorkspaceRelativePath(FileName)\r
305 FileName = os.path.splitext(FileName)[0] + ".inf"\r
306 FileName = FileName.replace("\\", "/")\r
307 return FileName\r
308\r
309# A global class object of EdkIIWorkspaceGuidsInfo for external reference.\r
310gEdkIIWorkspaceGuidsInfo = EdkIIWorkspaceGuidsInfo()\r
311\r
312# This acts like the main() function for the script, unless it is 'import'ed\r
313# into another script.\r
314if __name__ == '__main__':\r
315 # Test the translation of package Guid.\r
316 MdePkgGuid = "1E73767F-8F52-4603-AEB4-F29B510B6766"\r
317 OldMdePkgGuid = "5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"\r
318 print gEdkIIWorkspaceGuidsInfo.ResolveModuleFilePath(MdePkgGuid)\r
319 print gEdkIIWorkspaceGuidsInfo.ResolveModuleFilePath(OldMdePkgGuid)\r
320 \r
321 # Test the translation of module Guid.\r
322 UefiLibGuid = "3a004ba5-efe0-4a61-9f1a-267a46ae5ba9"\r
323 UefiDriverModelLibGuid = "52af22ae-9901-4484-8cdc-622dd5838b09"\r
324 print gEdkIIWorkspaceGuidsInfo.ResolveModuleFilePath(UefiLibGuid)\r
325 print gEdkIIWorkspaceGuidsInfo.ResolveModuleFilePath(UefiDriverModelLibGuid)\r