]>
git.proxmox.com Git - mirror_edk2.git/blob - Tools/Python/MkFar.py
3 """This is a python script that takes user input from the command line and
4 creates a far (Framework Archive Manifest) file for distribution."""
6 import os
, sys
, getopt
, string
, xml
.dom
.minidom
, zipfile
, md5
7 from XmlRoutines
import *
8 from WorkspaceRoutines
import *
11 """This class is used to collect arbitrarty data from the template file."""
13 """Assign the default values for the far fields."""
14 far
.FileName
= "output.far"
26 """The far object is constructed from the template file the user passed in."""
28 def parseMsa(msaFile
, spdDir
):
30 """ XXX Parse an msa file and return a list of all the files that this msa
35 msaDir
= os
.path
.dirname(msaFile
)
37 msa
= xml
.dom
.minidom
.parse(inWorkspace(os
.path
.join(spdDir
, msaFile
)))
40 "/ModuleSurfaceArea/SourceFiles/Filename",
41 "/ModuleSurfaceArea/NonProcessedFiles/Filename" ]
43 for xmlPath
in xmlPaths
:
44 for f
in XmlList(msa
, xmlPath
):
45 filelist
.append(str(os
.path
.join(msaDir
, XmlElementData(f
))))
49 def parseSpd(spdFile
):
51 """Parse an spd file and return a list of all the files that this spd
56 spdDir
= os
.path
.dirname(spdFile
)
58 spd
= xml
.dom
.minidom
.parse(inWorkspace(spdFile
))
61 "/PackageSurfaceArea/LibraryClassDeclarations/LibraryClass/IncludeHeader",
62 "/PackageSurfaceArea/IndustryStdIncludes/IndustryStdHeader/IncludeHeader",
63 "/PackageSurfaceArea/PackageHeaders/IncludePkgHeader" ]
65 for xmlPath
in xmlPaths
:
66 for f
in XmlList(spd
, xmlPath
):
67 files
.append(str(XmlElementData(f
)))
69 for f
in XmlList(spd
, "/PackageSurfaceArea/MsaFiles/Filename"):
70 msaFile
= str(XmlElementData(f
))
71 files
+= parseMsa(msaFile
, spdDir
)
74 os
.chdir(inWorkspace(spdDir
))
75 for root
, dirs
, entries
in os
.walk("Include"):
76 # Some files need to be skipped.
77 for r
in ["CVS", ".svn"]:
81 files
.append(os
.path
.join(os
.path
.normpath(root
), entry
))
86 def makeFarHeader(doc
):
88 """Create a dom tree for the Far Header. It will use information from the
89 template file passed on the command line, if present."""
91 header
= doc
.createElement("FarHeader")
92 name
= doc
.createElement("FarName")
93 name
.appendChild(doc
.createTextNode(far
.FarName
))
94 header
.appendChild(name
)
95 guidVal
= doc
.createElement("GuidValue")
96 guidVal
.appendChild(doc
.createTextNode(genguid()))
97 header
.appendChild(guidVal
)
98 ver
= doc
.createElement("Version")
99 ver
.appendChild(doc
.createTextNode(far
.Version
))
100 header
.appendChild(ver
)
101 abstract
= doc
.createElement("Abstract")
102 abstract
.appendChild(doc
.createTextNode(far
.Abstract
))
103 header
.appendChild(abstract
)
104 desc
= doc
.createElement("Description")
105 desc
.appendChild(doc
.createTextNode(far
.Description
))
106 header
.appendChild(desc
)
107 copy
= doc
.createElement("Copyright")
108 copy
.appendChild(doc
.createTextNode(far
.Copyright
))
109 header
.appendChild(copy
)
110 lic
= doc
.createElement("License")
111 lic
.appendChild(doc
.createTextNode(far
.License
))
112 header
.appendChild(lic
)
113 spec
= doc
.createElement("Specification")
114 spec
.appendChild(doc
.createTextNode("FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052"))
115 header
.appendChild(spec
)
119 def getSpdGuidVersion(spdFile
):
121 """Returns a tuple (guid, version) which is read from the given spdFile."""
123 spd
= xml
.dom
.minidom
.parse(inWorkspace(spdFile
))
125 return (XmlElement(spd
, "/PackageSurfaceArea/SpdHeader/GuidValue"),
126 XmlElement(spd
, "/PackageSurfaceArea/SpdHeader/Version"))
128 def makeFar(files
, farname
):
130 """Make a far out of the given filelist and writes it to the file farname."""
132 domImpl
= xml
.dom
.minidom
.getDOMImplementation()
133 man
= domImpl
.createDocument(None, "FrameworkArchiveManifest", None)
134 top_element
= man
.documentElement
136 top_element
.appendChild(makeFarHeader(man
))
138 packList
= man
.createElement("FarPackageList")
139 top_element
.appendChild(packList
)
141 platList
= man
.createElement("FarPlatformList")
142 top_element
.appendChild(platList
)
144 contents
= man
.createElement("Contents")
145 top_element
.appendChild(contents
)
147 exts
= man
.createElement("UserExtensions")
148 top_element
.appendChild(exts
)
150 zip = zipfile
.ZipFile(farname
, "w")
151 for infile
in set(files
):
152 if not os
.path
.exists(inWorkspace(infile
)):
153 print "Error: Non-existent file '%s'." % infile
155 (_
, extension
) = os
.path
.splitext(infile
)
156 if extension
== ".spd":
157 filelist
= parseSpd(infile
)
158 spdDir
= os
.path
.dirname(infile
)
160 (spdGuid
, spdVersion
) = getSpdGuidVersion(infile
)
162 package
= man
.createElement("FarPackage")
163 packList
.appendChild(package
)
165 spdfilename
= farFileNode(man
, inWorkspace(infile
))
166 zip.write(inWorkspace(infile
), infile
)
167 spdfilename
.appendChild(man
.createTextNode(lean(infile
)))
168 package
.appendChild(spdfilename
)
170 guidValue
= man
.createElement("GuidValue")
171 guidValue
.appendChild(man
.createTextNode(spdGuid
))
172 package
.appendChild(guidValue
)
174 version
= man
.createElement("Version")
175 version
.appendChild(man
.createTextNode(spdVersion
))
176 package
.appendChild(version
)
178 defaultPath
= man
.createElement("DefaultPath")
179 defaultPath
.appendChild(man
.createTextNode(spdDir
))
180 package
.appendChild(defaultPath
)
182 farPlatformList
= man
.createElement("FarPlatformList")
183 package
.appendChild(farPlatformList
)
185 packContents
= man
.createElement("Contents")
186 package
.appendChild(packContents
)
188 ue
= man
.createElement("UserExtensions")
189 package
.appendChild(ue
)
191 for spdfile
in filelist
:
192 content
= farFileNode(man
, inWorkspace(os
.path
.join(spdDir
, spdfile
)))
193 zip.write(inWorkspace(os
.path
.join(spdDir
, spdfile
)), os
.path
.join(spdDir
,spdfile
))
194 content
.appendChild(man
.createTextNode(lean(spdfile
)))
195 packContents
.appendChild(content
)
197 elif extension
== ".fpd":
199 platform
= man
.createElement("FarPlatform")
200 platList
.appendChild(platform
)
202 fpdfilename
= farFileNode(man
, inWorkspace(infile
))
203 zip.write(inWorkspace(infile
), infile
)
204 platform
.appendChild(fpdfilename
)
205 fpdfilename
.appendChild(man
.createTextNode(lean(infile
)))
208 content
= farFileNode(man
, inWorkspace(infile
))
209 zip.write(inWorkspace(infile
), infile
)
210 content
.appendChild(man
.createTextNode(lean(infile
)))
211 contents
.appendChild(content
)
213 zip.writestr("FrameworkArchiveManifest.xml", man
.toprettyxml(2*" "))
217 def farFileNode(doc
, filename
):
219 """This is a function that returns a dom tree for a given file that is
220 included in the far. An md5sum is calculated for that file."""
222 content
= doc
.createElement("FarFilename")
224 f
=open(filename
, "rb")
225 content
.setAttribute("Md5sum", md5
.md5(f
.read()).hexdigest())
228 print "Error: Unable to open file: %s" % filename
233 # This acts like the main() function for the script, unless it is 'import'ed
234 # into another script.
235 if __name__
== '__main__':
237 # Create a pretty printer for dumping data structures in a readable form.
238 # pp = pprint.PrettyPrinter(indent=2)
240 # Process the command line args.
241 optlist
, args
= getopt
.getopt(sys
.argv
[1:], 'hf:t:', [ 'template=', 'far=', 'help'])
243 # First pass through the options list.
245 if o
in ["-h", "--help"]:
247 Pass a list of .spd and .fpd files to be placed into a far for distribution.
248 You may give the name of the far with a -f or --far option. For example:
250 %s --template far-template --far library.far MdePkg/MdePkg.spd
252 The file paths of .spd and .fpd are treated as relative to the WORKSPACE
253 environment variable which must be set to a valid workspace root directory.
255 A template file may be passed in with the --template option. This template file
256 is a text file that allows more contol over the contents of the far.
257 """ % os
.path
.basename(sys
.argv
[0])
260 optlist
.remove((o
,a
))
261 if o
in ["-t", "--template"]:
262 # The template file is processed first, so that command line options can
265 execfile(templateName
)
266 optlist
.remove((o
,a
))
268 # Second pass through the options list. These can override the first pass.
271 if o
in ["-f", "--far"]:
274 # Let's err on the side of caution and not let people blow away data
276 if os
.path
.exists(far
.FileName
):
277 print "Error: File %s exists. Not overwriting." % far
.FileName
280 makeFar(far
.SpdFiles
+ far
.FpdFiles
+ far
.ExtraFiles
+ args
, far
.FileName
)