]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/Common/MigrationUtilities.py
BaseTools: Clear build versions to sync with buildtools/BaseTools
[mirror_edk2.git] / BaseTools / Source / Python / Common / MigrationUtilities.py
1 ## @file
2 # Contains several utilitities shared by migration tools.
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 re
19 import EdkLogger
20 from optparse import OptionParser
21 from Common.BuildToolError import *
22 from XmlRoutines import *
23 from CommonDataClass.CommonClass import *
24
25 ## Set all fields of CommonClass object.
26 #
27 # Set all attributes of CommonClass object from XML Dom object of XmlCommon.
28 #
29 # @param Common The destine CommonClass object.
30 # @param XmlCommon The source XML Dom object.
31 #
32 def SetCommon(Common, XmlCommon):
33 XmlTag = "Usage"
34 Common.Usage = XmlAttribute(XmlCommon, XmlTag).split()
35
36 XmlTag = "FeatureFlag"
37 Common.FeatureFlag = XmlAttribute(XmlCommon, XmlTag)
38
39 XmlTag = "SupArchList"
40 Common.SupArchList = XmlAttribute(XmlCommon, XmlTag).split()
41
42 XmlTag = XmlNodeName(XmlCommon) + "/" + "HelpText"
43 Common.HelpText = XmlElement(XmlCommon, XmlTag)
44
45
46 ## Set some fields of CommonHeaderClass object.
47 #
48 # Set Name, Guid, FileName and FullPath fields of CommonHeaderClass object from
49 # XML Dom object of XmlCommonHeader, NameTag and FileName.
50 #
51 # @param CommonHeader The destine CommonClass object.
52 # @param XmlCommonHeader The source XML Dom object.
53 # @param NameTag The name tag in XML Dom object.
54 # @param FileName The file name of the XML file.
55 #
56 def SetIdentification(CommonHeader, XmlCommonHeader, NameTag, FileName):
57 XmlParentTag = XmlNodeName(XmlCommonHeader)
58
59 XmlTag = XmlParentTag + "/" + NameTag
60 CommonHeader.Name = XmlElement(XmlCommonHeader, XmlTag)
61
62 XmlTag = XmlParentTag + "/" + "GuidValue"
63 CommonHeader.Guid = XmlElement(XmlCommonHeader, XmlTag)
64
65 XmlTag = XmlParentTag + "/" + "Version"
66 CommonHeader.Version = XmlElement(XmlCommonHeader, XmlTag)
67
68 CommonHeader.FileName = os.path.basename(FileName)
69 CommonHeader.FullPath = os.path.abspath(FileName)
70
71
72 ## Regular expression to match specification and value.
73 mReSpecification = re.compile(r"(?P<Specification>\w+)\s+(?P<Value>\w*)")
74
75 ## Add specification to specification dictionary.
76 #
77 # Abstract specification name, value pair from Specification String and add them
78 # to specification dictionary.
79 #
80 # @param SpecificationDict The destine Specification dictionary.
81 # @param SpecificationString The source Specification String from which the
82 # specification name and value pair is abstracted.
83 #
84 def AddToSpecificationDict(SpecificationDict, SpecificationString):
85 """Abstract specification name, value pair from Specification String"""
86 for SpecificationMatch in mReSpecification.finditer(SpecificationString):
87 Specification = SpecificationMatch.group("Specification")
88 Value = SpecificationMatch.group("Value")
89 SpecificationDict[Specification] = Value
90
91 ## Set all fields of CommonHeaderClass object.
92 #
93 # Set all attributes of CommonHeaderClass object from XML Dom object of
94 # XmlCommonHeader, NameTag and FileName.
95 #
96 # @param CommonHeader The destine CommonClass object.
97 # @param XmlCommonHeader The source XML Dom object.
98 # @param NameTag The name tag in XML Dom object.
99 # @param FileName The file name of the XML file.
100 #
101 def SetCommonHeader(CommonHeader, XmlCommonHeader):
102 """Set all attributes of CommonHeaderClass object from XmlCommonHeader"""
103 XmlParent = XmlNodeName(XmlCommonHeader)
104
105 XmlTag = XmlParent + "/" + "Abstract"
106 CommonHeader.Abstract = XmlElement(XmlCommonHeader, XmlTag)
107
108 XmlTag = XmlParent + "/" + "Description"
109 CommonHeader.Description = XmlElement(XmlCommonHeader, XmlTag)
110
111 XmlTag = XmlParent + "/" + "Copyright"
112 CommonHeader.Copyright = XmlElement(XmlCommonHeader, XmlTag)
113
114 XmlTag = XmlParent + "/" + "License"
115 CommonHeader.License = XmlElement(XmlCommonHeader, XmlTag)
116
117 XmlTag = XmlParent + "/" + "Specification"
118 Specification = XmlElement(XmlCommonHeader, XmlTag)
119
120 AddToSpecificationDict(CommonHeader.Specification, Specification)
121
122 XmlTag = XmlParent + "/" + "ModuleType"
123 CommonHeader.ModuleType = XmlElement(XmlCommonHeader, XmlTag)
124
125
126 ## Load a new Cloned Record class object.
127 #
128 # Read an input XML ClonedRecord DOM object and return an object of Cloned Record
129 # contained in the DOM object.
130 #
131 # @param XmlCloned A child XML DOM object in a Common XML DOM.
132 #
133 # @retvel ClonedRecord A new Cloned Record object created by XmlCloned.
134 #
135 def LoadClonedRecord(XmlCloned):
136 ClonedRecord = ClonedRecordClass()
137
138 XmlTag = "Id"
139 ClonedRecord.Id = int(XmlAttribute(XmlCloned, XmlTag))
140
141 XmlTag = "FarGuid"
142 ClonedRecord.FarGuid = XmlAttribute(XmlCloned, XmlTag)
143
144 XmlTag = "Cloned/PackageGuid"
145 ClonedRecord.PackageGuid = XmlElement(XmlCloned, XmlTag)
146
147 XmlTag = "Cloned/PackageVersion"
148 ClonedRecord.PackageVersion = XmlElement(XmlCloned, XmlTag)
149
150 XmlTag = "Cloned/ModuleGuid"
151 ClonedRecord.ModuleGuid = XmlElement(XmlCloned, XmlTag)
152
153 XmlTag = "Cloned/ModuleVersion"
154 ClonedRecord.ModuleVersion = XmlElement(XmlCloned, XmlTag)
155
156 return ClonedRecord
157
158
159 ## Load a new Guid/Protocol/Ppi common class object.
160 #
161 # Read an input XML Guid/Protocol/Ppi DOM object and return an object of
162 # Guid/Protocol/Ppi contained in the DOM object.
163 #
164 # @param XmlGuidProtocolPpiCommon A child XML DOM object in a Common XML DOM.
165 #
166 # @retvel GuidProtocolPpiCommon A new GuidProtocolPpiCommon class object
167 # created by XmlGuidProtocolPpiCommon.
168 #
169 def LoadGuidProtocolPpiCommon(XmlGuidProtocolPpiCommon):
170 GuidProtocolPpiCommon = GuidProtocolPpiCommonClass()
171
172 XmlTag = "Name"
173 GuidProtocolPpiCommon.Name = XmlAttribute(XmlGuidProtocolPpiCommon, XmlTag)
174
175 XmlParent = XmlNodeName(XmlGuidProtocolPpiCommon)
176 if XmlParent == "Entry":
177 XmlTag = "%s/C_Name" % XmlParent
178 elif XmlParent == "GuidCNames":
179 XmlTag = "%s/GuidCName" % XmlParent
180 else:
181 XmlTag = "%s/%sCName" % (XmlParent, XmlParent)
182
183 GuidProtocolPpiCommon.CName = XmlElement(XmlGuidProtocolPpiCommon, XmlTag)
184
185 XmlTag = XmlParent + "/" + "GuidValue"
186 GuidProtocolPpiCommon.Guid = XmlElement(XmlGuidProtocolPpiCommon, XmlTag)
187
188 if XmlParent.endswith("Notify"):
189 GuidProtocolPpiCommon.Notify = True
190
191 XmlTag = "GuidTypeList"
192 GuidTypes = XmlAttribute(XmlGuidProtocolPpiCommon, XmlTag)
193 GuidProtocolPpiCommon.GuidTypeList = GuidTypes.split()
194
195 XmlTag = "SupModuleList"
196 SupModules = XmlAttribute(XmlGuidProtocolPpiCommon, XmlTag)
197 GuidProtocolPpiCommon.SupModuleList = SupModules.split()
198
199 SetCommon(GuidProtocolPpiCommon, XmlGuidProtocolPpiCommon)
200
201 return GuidProtocolPpiCommon
202
203
204 ## Load a new Pcd class object.
205 #
206 # Read an input XML Pcd DOM object and return an object of Pcd
207 # contained in the DOM object.
208 #
209 # @param XmlPcd A child XML DOM object in a Common XML DOM.
210 #
211 # @retvel Pcd A new Pcd object created by XmlPcd.
212 #
213 def LoadPcd(XmlPcd):
214 """Return a new PcdClass object equivalent to XmlPcd"""
215 Pcd = PcdClass()
216
217 XmlTag = "PcdEntry/C_Name"
218 Pcd.CName = XmlElement(XmlPcd, XmlTag)
219
220 XmlTag = "PcdEntry/Token"
221 Pcd.Token = XmlElement(XmlPcd, XmlTag)
222
223 XmlTag = "PcdEntry/TokenSpaceGuidCName"
224 Pcd.TokenSpaceGuidCName = XmlElement(XmlPcd, XmlTag)
225
226 XmlTag = "PcdEntry/DatumType"
227 Pcd.DatumType = XmlElement(XmlPcd, XmlTag)
228
229 XmlTag = "PcdEntry/MaxDatumSize"
230 Pcd.MaxDatumSize = XmlElement(XmlPcd, XmlTag)
231
232 XmlTag = "PcdEntry/DefaultValue"
233 Pcd.DefaultValue = XmlElement(XmlPcd, XmlTag)
234
235 XmlTag = "PcdItemType"
236 Pcd.ItemType = XmlAttribute(XmlPcd, XmlTag)
237
238 XmlTag = "PcdEntry/ValidUsage"
239 Pcd.ValidUsage = XmlElement(XmlPcd, XmlTag).split()
240
241 XmlTag = "SupModuleList"
242 Pcd.SupModuleList = XmlAttribute(XmlPcd, XmlTag).split()
243
244 SetCommon(Pcd, XmlPcd)
245
246 return Pcd
247
248
249 ## Load a new LibraryClass class object.
250 #
251 # Read an input XML LibraryClass DOM object and return an object of LibraryClass
252 # contained in the DOM object.
253 #
254 # @param XmlLibraryClass A child XML DOM object in a Common XML DOM.
255 #
256 # @retvel LibraryClass A new LibraryClass object created by XmlLibraryClass.
257 #
258 def LoadLibraryClass(XmlLibraryClass):
259 LibraryClass = LibraryClassClass()
260
261 XmlTag = "LibraryClass/Keyword"
262 LibraryClass.LibraryClass = XmlElement(XmlLibraryClass, XmlTag)
263 if LibraryClass.LibraryClass == "":
264 XmlTag = "Name"
265 LibraryClass.LibraryClass = XmlAttribute(XmlLibraryClass, XmlTag)
266
267 XmlTag = "LibraryClass/IncludeHeader"
268 LibraryClass.IncludeHeader = XmlElement(XmlLibraryClass, XmlTag)
269
270 XmlTag = "RecommendedInstanceVersion"
271 RecommendedInstanceVersion = XmlAttribute(XmlLibraryClass, XmlTag)
272 LibraryClass.RecommendedInstanceVersion = RecommendedInstanceVersion
273
274 XmlTag = "RecommendedInstanceGuid"
275 RecommendedInstanceGuid = XmlAttribute(XmlLibraryClass, XmlTag)
276 LibraryClass.RecommendedInstanceGuid = RecommendedInstanceGuid
277
278 XmlTag = "SupModuleList"
279 SupModules = XmlAttribute(XmlLibraryClass, XmlTag)
280 LibraryClass.SupModuleList = SupModules.split()
281
282 SetCommon(LibraryClass, XmlLibraryClass)
283
284 return LibraryClass
285
286
287 ## Load a new Build Option class object.
288 #
289 # Read an input XML BuildOption DOM object and return an object of Build Option
290 # contained in the DOM object.
291 #
292 # @param XmlBuildOption A child XML DOM object in a Common XML DOM.
293 #
294 # @retvel BuildOption A new Build Option object created by XmlBuildOption.
295 #
296 def LoadBuildOption(XmlBuildOption):
297 """Return a new BuildOptionClass object equivalent to XmlBuildOption"""
298 BuildOption = BuildOptionClass()
299
300 BuildOption.Option = XmlElementData(XmlBuildOption)
301
302 XmlTag = "BuildTargets"
303 BuildOption.BuildTargetList = XmlAttribute(XmlBuildOption, XmlTag).split()
304
305 XmlTag = "ToolChainFamily"
306 BuildOption.ToolChainFamily = XmlAttribute(XmlBuildOption, XmlTag)
307
308 XmlTag = "TagName"
309 BuildOption.TagName = XmlAttribute(XmlBuildOption, XmlTag)
310
311 XmlTag = "ToolCode"
312 BuildOption.ToolCode = XmlAttribute(XmlBuildOption, XmlTag)
313
314 XmlTag = "SupArchList"
315 BuildOption.SupArchList = XmlAttribute(XmlBuildOption, XmlTag).split()
316
317 return BuildOption
318
319
320 ## Load a new User Extensions class object.
321 #
322 # Read an input XML UserExtensions DOM object and return an object of User
323 # Extensions contained in the DOM object.
324 #
325 # @param XmlUserExtensions A child XML DOM object in a Common XML DOM.
326 #
327 # @retvel UserExtensions A new User Extensions object created by
328 # XmlUserExtensions.
329 #
330 def LoadUserExtensions(XmlUserExtensions):
331 UserExtensions = UserExtensionsClass()
332
333 XmlTag = "UserID"
334 UserExtensions.UserID = XmlAttribute(XmlUserExtensions, XmlTag)
335
336 XmlTag = "Identifier"
337 UserExtensions.Identifier = XmlAttribute(XmlUserExtensions, XmlTag)
338
339 UserExtensions.Content = XmlElementData(XmlUserExtensions)
340
341 return UserExtensions
342
343
344 ## Store content to a text file object.
345 #
346 # Write some text file content to a text file object. The contents may echo
347 # in screen in a verbose way.
348 #
349 # @param TextFile The text file object.
350 # @param Content The string object to be written to a text file.
351 #
352 def StoreTextFile(TextFile, Content):
353 EdkLogger.verbose(Content)
354 TextFile.write(Content)
355
356
357 ## Add item to a section.
358 #
359 # Add an Item with specific CPU architecture to section dictionary.
360 # The possible duplication is ensured to be removed.
361 #
362 # @param Section Section dictionary indexed by CPU architecture.
363 # @param Arch CPU architecture: Ia32, X64, Ipf, ARM, AARCH64, Ebc or Common.
364 # @param Item The Item to be added to section dictionary.
365 #
366 def AddToSection(Section, Arch, Item):
367 SectionArch = Section.get(Arch, [])
368 if Item not in SectionArch:
369 SectionArch.append(Item)
370 Section[Arch] = SectionArch
371
372
373 ## Get section contents.
374 #
375 # Return the content of section named SectionName.
376 # the contents is based on Methods and ObjectLists.
377 #
378 # @param SectionName The name of the section.
379 # @param Method A function returning a string item of an object.
380 # @param ObjectList The list of object.
381 #
382 # @retval Section The string content of a section.
383 #
384 def GetSection(SectionName, Method, ObjectList):
385 SupportedArches = ["common", "Ia32", "X64", "Ipf", "Ebc", "ARM", "AARCH64"]
386 SectionDict = {}
387 for Object in ObjectList:
388 Item = Method(Object)
389 if Item == "":
390 continue
391 Item = " %s" % Item
392 Arches = Object.SupArchList
393 if len(Arches) == 0:
394 AddToSection(SectionDict, "common", Item)
395 else:
396 for Arch in SupportedArches:
397 if Arch.upper() in Arches:
398 AddToSection(SectionDict, Arch, Item)
399
400 Section = ""
401 for Arch in SupportedArches:
402 SectionArch = "\n".join(SectionDict.get(Arch, []))
403 if SectionArch != "":
404 Section += "[%s.%s]\n%s\n" % (SectionName, Arch, SectionArch)
405 Section += "\n"
406 if Section != "":
407 Section += "\n"
408 return Section
409
410
411 ## Store file header to a text file.
412 #
413 # Write standard file header to a text file. The content includes copyright,
414 # abstract, description and license extracted from CommonHeader class object.
415 #
416 # @param TextFile The text file object.
417 # @param CommonHeader The source CommonHeader class object.
418 #
419 def StoreHeader(TextFile, CommonHeader):
420 CopyRight = CommonHeader.Copyright
421 Abstract = CommonHeader.Abstract
422 Description = CommonHeader.Description
423 License = CommonHeader.License
424
425 Header = "#/** @file\n#\n"
426 Header += "# " + Abstract + "\n#\n"
427 Header += "# " + Description.strip().replace("\n", "\n# ") + "\n"
428 Header += "# " + CopyRight + "\n#\n"
429 Header += "# " + License.replace("\n", "\n# ").replace(" ", " ")
430 Header += "\n#\n#**/\n\n"
431
432 StoreTextFile(TextFile, Header)
433
434 ## Store file header to a text file.
435 #
436 # Write Defines section to a text file. DefinesTupleList determines the content.
437 #
438 # @param TextFile The text file object.
439 # @param DefinesTupleList The list of (Tag, Value) to be added as one item.
440 #
441 def StoreDefinesSection(TextFile, DefinesTupleList):
442 Section = "[Defines]\n"
443 for DefineItem in DefinesTupleList:
444 Section += " %-30s = %s\n" % DefineItem
445
446 Section += "\n\n"
447 StoreTextFile(TextFile, Section)
448
449
450 ## Return one User Extension section.
451 #
452 # Read the input UserExtentsions class object and return one section.
453 #
454 # @param UserExtensions An input UserExtensions class object.
455 #
456 # @retval UserExtensionSection A section representing UserExtensions object.
457 #
458 def GetUserExtensions(UserExtensions):
459 UserId = UserExtensions.UserID
460 Identifier = UserExtensions.Identifier
461 Content = UserExtensions.Content
462
463 return "[UserExtensions.%s.%s]\n %s\n\n" % (UserId, Identifier, Content)
464
465 ## Regular expression to match an equation.
466 mReEquation = re.compile(r"\s*(\S+)\s*=\s*(\S*)\s*")
467
468 ## Return a value tuple matching information in a text fle.
469 #
470 # Parse the text file and return a value tuple corresponding to an input tag
471 # tuple. In case of any error, an tuple of empty strings is returned.
472 #
473 # @param FileName The file name of the text file.
474 # @param TagTuple A tuple of tags as the key to the value.
475 #
476 # @param ValueTupe The returned tuple corresponding to the tag tuple.
477 #
478 def GetTextFileInfo(FileName, TagTuple):
479 ValueTuple = [""] * len(TagTuple)
480 try:
481 for Line in open(FileName):
482 Line = Line.split("#", 1)[0]
483 MatchEquation = mReEquation.match(Line)
484 if MatchEquation:
485 Tag = MatchEquation.group(1).upper()
486 Value = MatchEquation.group(2)
487 for Index in range(len(TagTuple)):
488 if TagTuple[Index] == Tag:
489 ValueTuple[Index] = Value
490 except:
491 EdkLogger.info("IO Error in reading file %s" % FileName)
492
493 return ValueTuple
494
495
496 ## Return a value tuple matching information in an XML fle.
497 #
498 # Parse the XML file and return a value tuple corresponding to an input tag
499 # tuple. In case of any error, an tuple of empty strings is returned.
500 #
501 # @param FileName The file name of the XML file.
502 # @param TagTuple A tuple of tags as the key to the value.
503 #
504 # @param ValueTupe The returned tuple corresponding to the tag tuple.
505 #
506 def GetXmlFileInfo(FileName, TagTuple):
507 XmlDom = XmlParseFile(FileName)
508 return tuple([XmlElement(XmlDom, XmlTag) for XmlTag in TagTuple])
509
510
511 ## Parse migration command line options
512 #
513 # Use standard Python module optparse to parse command line option of this tool.
514 #
515 # @param Source The source file type.
516 # @param Destinate The destinate file type.
517 #
518 # @retval Options A optparse object containing the parsed options.
519 # @retval InputFile Path of an source file to be migrated.
520 #
521 def MigrationOptionParser(Source, Destinate, ToolName, VersionNumber = 1.0):
522 # use clearer usage to override default usage message
523 UsageString = "%s [-a] [-v|-q] [-o <output_file>] <input_file>" % ToolName
524 Version = "%s Version %.2f" % (ToolName, VersionNumber)
525 Copyright = "Copyright (c) 2007, Intel Corporation. All rights reserved."
526
527 Parser = OptionParser(description=Copyright, version=Version, usage=UsageString)
528 Parser.add_option("-o", "--output", dest="OutputFile", help="The name of the %s file to be created." % Destinate)
529 Parser.add_option("-a", "--auto", dest="AutoWrite", action="store_true", default=False, help="Automatically create the %s file using the name of the %s file and replacing file extension" % (Source, Destinate))
530 Parser.add_option("-q", "--quiet", action="store_true", type=None, help="Disable all messages except FATAL ERRORS.")
531 Parser.add_option("-v", "--verbose", action="store_true", type=None, help="Turn on verbose output with informational messages printed.")
532
533 Options, Args = Parser.parse_args()
534
535 # Set logging level
536 if Options.verbose:
537 EdkLogger.setLevel(EdkLogger.VERBOSE)
538 elif Options.quiet:
539 EdkLogger.setLevel(EdkLogger.QUIET)
540 else:
541 EdkLogger.setLevel(EdkLogger.INFO)
542
543 # error check
544 if len(Args) == 0:
545 raise MigrationError(PARAMETER_MISSING, name="Input file", usage=Parser.get_usage())
546 if len(Args) > 1:
547 raise MigrationError(PARAMETER_INVALID, name="Too many input files", usage=Parser.get_usage())
548
549 InputFile = Args[0]
550 if not os.path.exists(InputFile):
551 raise MigrationError(FILE_NOT_FOUND, name=InputFile)
552
553 if Options.OutputFile:
554 if Options.AutoWrite:
555 raise MigrationError(OPTION_CONFLICT, arg1="-o", arg2="-a", usage=Parser.get_usage())
556 else:
557 if Options.AutoWrite:
558 Options.OutputFile = os.path.splitext(InputFile)[0] + "." + Destinate.lower()
559 else:
560 raise MigrationError(OPTION_MISSING, name="-o", usage=Parser.get_usage())
561
562 return Options, InputFile
563
564 # This acts like the main() function for the script, unless it is 'import'ed
565 # into another script.
566 if __name__ == '__main__':
567 pass