Correct the sample instruction.
[mirror_edk2.git] / Tools / Python / MkFar.py
CommitLineData
e853a9d4 1#!/usr/bin/env python
2
10d6603f 3import os, sys, getopt, string, xml.dom.minidom, zipfile, md5
e853a9d4 4from XmlRoutines import *
5from WorkspaceRoutines import *
6
fb96878e 7class Far:
8 """This class is used to collect arbitrarty data from the template file."""
9 def __init__(far):
10 """Assign the default values for the far fields."""
11 far.FileName = "output.far"
12 far.FarName=""
13 far.Version=""
14 far.License=""
af2efcaf 15 far.Abstract=""
fb96878e 16 far.Description=""
17 far.Copyright=""
af2efcaf 18 far.SpdFiles=[]
19 far.FpdFiles=[]
20 far.ExtraFiles=[]
fb96878e 21
22far = Far()
23
e853a9d4 24def parseMsa(msaFile, spdDir):
25
69932b41 26 filelist = [msaFile]
e853a9d4 27
28 msaDir = os.path.dirname(msaFile)
29
10d6603f 30 msa = xml.dom.minidom.parse(inWorkspace(os.path.join(spdDir, msaFile)))
e853a9d4 31
32 xmlPaths = [
10d6603f 33 "/ModuleSurfaceArea/SourceFiles/Filename",
34 "/ModuleSurfaceArea/NonProcessedFiles/Filename" ]
35
e853a9d4 36 for xmlPath in xmlPaths:
37 for f in XmlList(msa, xmlPath):
38 filelist.append(str(os.path.join(msaDir, XmlElementData(f))))
39
40 return filelist
41
42def parseSpd(spdFile):
43
10d6603f 44 files = []
e853a9d4 45
46 spdDir = os.path.dirname(spdFile)
47
48 spd = xml.dom.minidom.parse(inWorkspace(spdFile))
49
50 xmlPaths = [
51 "/PackageSurfaceArea/LibraryClassDeclarations/LibraryClass/IncludeHeader",
52 "/PackageSurfaceArea/IndustryStdIncludes/IndustryStdHeader/IncludeHeader",
3ff56e5e 53 "/PackageSurfaceArea/PackageHeaders/IncludePkgHeader" ]
e853a9d4 54
55 for xmlPath in xmlPaths:
56 for f in XmlList(spd, xmlPath):
10d6603f 57 files.append(str(XmlElementData(f)))
e853a9d4 58
d32aaa95 59 for f in XmlList(spd, "/PackageSurfaceArea/MsaFiles/Filename"):
10d6603f 60 msaFile = str(XmlElementData(f))
61 files += parseMsa(msaFile, spdDir)
62
63 cwd = os.getcwd()
64 os.chdir(inWorkspace(spdDir))
65 for root, dirs, entries in os.walk("Include"):
af2efcaf 66 # Some files need to be skipped.
67 for r in ["CVS", ".svn"]:
10d6603f 68 if r in dirs:
69 dirs.remove(r)
70 for entry in entries:
71 files.append(os.path.join(os.path.normpath(root), entry))
72 os.chdir(cwd)
73
74 return files
75
76def makeFarHeader(doc):
77
78 header = doc.createElement("FarHeader")
79 name = doc.createElement("FarName")
fb96878e 80 name.appendChild(doc.createTextNode(far.FarName))
10d6603f 81 header.appendChild(name)
82 guidVal = doc.createElement("GuidValue")
83 guidVal.appendChild(doc.createTextNode(genguid()))
84 header.appendChild(guidVal)
85 ver = doc.createElement("Version")
fb96878e 86 ver.appendChild(doc.createTextNode(far.Version))
10d6603f 87 header.appendChild(ver)
88 abstract = doc.createElement("Abstract")
fb96878e 89 abstract.appendChild(doc.createTextNode(far.Abstract))
10d6603f 90 header.appendChild(abstract)
91 desc = doc.createElement("Description")
fb96878e 92 desc.appendChild(doc.createTextNode(far.Description))
10d6603f 93 header.appendChild(desc)
94 copy = doc.createElement("Copyright")
fb96878e 95 copy.appendChild(doc.createTextNode(far.Copyright))
10d6603f 96 header.appendChild(copy)
97 lic = doc.createElement("License")
fb96878e 98 lic.appendChild(doc.createTextNode(far.License))
10d6603f 99 header.appendChild(lic)
100 spec = doc.createElement("Specification")
101 spec.appendChild(doc.createTextNode("FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052"))
102 header.appendChild(spec)
103
104 return header
105
106def getSpdGuidVersion(spdFile):
e853a9d4 107
10d6603f 108 spd = xml.dom.minidom.parse(inWorkspace(spdFile))
109
110 return (XmlElement(spd, "/PackageSurfaceArea/SpdHeader/GuidValue"),
111 XmlElement(spd, "/PackageSurfaceArea/SpdHeader/Version"))
e853a9d4 112
af2efcaf 113def makeFar(files, farname):
e853a9d4 114
69932b41 115 domImpl = xml.dom.minidom.getDOMImplementation()
116 man = domImpl.createDocument(None, "FrameworkArchiveManifest", None)
117 top_element = man.documentElement
118
10d6603f 119 top_element.appendChild(makeFarHeader(man))
d32aaa95 120
69932b41 121 packList = man.createElement("FarPackageList")
122 top_element.appendChild(packList)
d32aaa95 123
69932b41 124 platList = man.createElement("FarPlatformList")
125 top_element.appendChild(platList)
d32aaa95 126
69932b41 127 contents = man.createElement("Contents")
128 top_element.appendChild(contents)
d32aaa95 129
10d6603f 130 exts = man.createElement("UserExtensions")
131 top_element.appendChild(exts)
132
e853a9d4 133 zip = zipfile.ZipFile(farname, "w")
af2efcaf 134 for infile in set(files):
d32aaa95 135 if not os.path.exists(inWorkspace(infile)):
136 print "Skipping non-existent file '%s'." % infile
137 (_, extension) = os.path.splitext(infile)
e853a9d4 138 if extension == ".spd":
d32aaa95 139 filelist = parseSpd(infile)
10d6603f 140 spdDir = os.path.dirname(infile)
141
142 (spdGuid, spdVersion) = getSpdGuidVersion(infile)
69932b41 143
d32aaa95 144 package = man.createElement("FarPackage")
145 packList.appendChild(package)
69932b41 146
10d6603f 147 spdfilename = farFileNode(man, inWorkspace(infile))
148 zip.write(inWorkspace(infile), infile)
af2efcaf 149 spdfilename.appendChild(man.createTextNode(lean(infile)))
d32aaa95 150 package.appendChild(spdfilename)
69932b41 151
10d6603f 152 guidValue = man.createElement("GuidValue")
153 guidValue.appendChild(man.createTextNode(spdGuid))
154 package.appendChild(guidValue)
155
156 version = man.createElement("Version")
157 version.appendChild(man.createTextNode(spdVersion))
158 package.appendChild(version)
159
160 defaultPath = man.createElement("DefaultPath")
161 defaultPath.appendChild(man.createTextNode(spdDir))
162 package.appendChild(defaultPath)
163
164 farPlatformList = man.createElement("FarPlatformList")
165 package.appendChild(farPlatformList)
166
167 packContents = man.createElement("Contents")
168 package.appendChild(packContents)
169
170 ue = man.createElement("UserExtensions")
171 package.appendChild(ue)
d32aaa95 172
173 for spdfile in filelist:
10d6603f 174 content = farFileNode(man, inWorkspace(os.path.join(spdDir, spdfile)))
175 zip.write(inWorkspace(os.path.join(spdDir, spdfile)), spdfile)
af2efcaf 176 content.appendChild(man.createTextNode(lean(spdfile)))
10d6603f 177 packContents.appendChild(content)
69932b41 178
e853a9d4 179 elif extension == ".fpd":
d32aaa95 180
181 platform = man.createElement("FarPlatform")
182 platList.appendChild(platform)
183
10d6603f 184 fpdfilename = farFileNode(man, inWorkspace(infile))
185 zip.write(inWorkspace(infile), infile)
d32aaa95 186 platform.appendChild(fpdfilename)
af2efcaf 187 fpdfilename.appendChild(man.createTextNode(lean(infile)))
d32aaa95 188
e853a9d4 189 else:
10d6603f 190 content = farFileNode(man, inWorkspace(infile))
191 zip.write(inWorkspace(infile), infile)
af2efcaf 192 content.appendChild(man.createTextNode(lean(infile)))
10d6603f 193 contents.appendChild(content)
d32aaa95 194
d0f7ef3e 195 zip.writestr("FrameworkArchiveManifest.xml", man.toprettyxml(2*" "))
e853a9d4 196 zip.close()
197 return
198
10d6603f 199def farFileNode(doc, filename):
200 content = doc.createElement("FarFilename")
201 f=open(filename, "rb")
202 content.setAttribute("Md5sum", md5.md5(f.read()).hexdigest())
203 f.close()
204 return content
205
d0f7ef3e 206# This acts like the main() function for the script, unless it is 'import'ed
207# into another script.
e853a9d4 208if __name__ == '__main__':
209
210 # Create a pretty printer for dumping data structures in a readable form.
211 # pp = pprint.PrettyPrinter(indent=2)
212
213 # Process the command line args.
fb96878e 214 optlist, args = getopt.getopt(sys.argv[1:], 'hf:t:', [ 'template=', 'far=', 'help'])
d0f7ef3e 215
af2efcaf 216 # First pass through the options list.
d0f7ef3e 217 for o, a in optlist:
218 if o in ["-h", "--help"]:
219 print """
220Pass a list of .spd and .fpd files to be placed into a far for distribution.
221You may give the name of the far with a -f or --far option. For example:
222
223 %s --far library.far MdePkg/MdePkg.spd
224
fb96878e 225The file paths of .spd and .fpd are treated as relative to the WORKSPACE
af2efcaf 226environment variable which must be set to a valid workspace root directory.
d0f7ef3e 227""" % os.path.basename(sys.argv[0])
228
229 sys.exit()
af2efcaf 230 optlist.remove((o,a))
fb96878e 231 if o in ["-t", "--template"]:
232 # The template file is processed first, so that command line options can
233 # override it.
234 templateName = a
235 execfile(templateName)
af2efcaf 236 optlist.remove((o,a))
237
238 # Second pass through the options list. These can override the first pass.
239 for o, a in optlist:
240 print o, a
d0f7ef3e 241 if o in ["-f", "--far"]:
fb96878e 242 far.FileName = a
e853a9d4 243
af2efcaf 244 # Let's err on the side of caution and not let people blow away data
245 # accidentally.
246 if os.path.exists(far.FileName):
247 print "Error: File %s exists. Not overwriting." % far.FileName
248 sys.exit()
249
250 makeFar(far.SpdFiles + far.FpdFiles + far.ExtraFiles + args, far.FileName)