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