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