1. Fix EDKT413: EnumerationData.java should use defined final static string
[mirror_edk2.git] / Tools / Python / MkFar.py
1 #!/usr/bin/env python
2
3 import os, sys, getopt, string, xml.dom.minidom, zipfile, md5
4 from XmlRoutines import *
5 from WorkspaceRoutines import *
6
7 class 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=""
15 far.Abstract=""
16 far.Description=""
17 far.Copyright=""
18 far.SpdFiles=[]
19 far.FpdFiles=[]
20 far.ExtraFiles=[]
21
22 far = Far()
23
24 def parseMsa(msaFile, spdDir):
25
26 filelist = [msaFile]
27
28 msaDir = os.path.dirname(msaFile)
29
30 msa = xml.dom.minidom.parse(inWorkspace(os.path.join(spdDir, msaFile)))
31
32 xmlPaths = [
33 "/ModuleSurfaceArea/SourceFiles/Filename",
34 "/ModuleSurfaceArea/NonProcessedFiles/Filename" ]
35
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
42 def parseSpd(spdFile):
43
44 files = []
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",
53 "/PackageSurfaceArea/PackageHeaders/IncludePkgHeader" ]
54
55 for xmlPath in xmlPaths:
56 for f in XmlList(spd, xmlPath):
57 files.append(str(XmlElementData(f)))
58
59 for f in XmlList(spd, "/PackageSurfaceArea/MsaFiles/Filename"):
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"):
66 # Some files need to be skipped.
67 for r in ["CVS", ".svn"]:
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
76 def makeFarHeader(doc):
77
78 header = doc.createElement("FarHeader")
79 name = doc.createElement("FarName")
80 name.appendChild(doc.createTextNode(far.FarName))
81 header.appendChild(name)
82 guidVal = doc.createElement("GuidValue")
83 guidVal.appendChild(doc.createTextNode(genguid()))
84 header.appendChild(guidVal)
85 ver = doc.createElement("Version")
86 ver.appendChild(doc.createTextNode(far.Version))
87 header.appendChild(ver)
88 abstract = doc.createElement("Abstract")
89 abstract.appendChild(doc.createTextNode(far.Abstract))
90 header.appendChild(abstract)
91 desc = doc.createElement("Description")
92 desc.appendChild(doc.createTextNode(far.Description))
93 header.appendChild(desc)
94 copy = doc.createElement("Copyright")
95 copy.appendChild(doc.createTextNode(far.Copyright))
96 header.appendChild(copy)
97 lic = doc.createElement("License")
98 lic.appendChild(doc.createTextNode(far.License))
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
106 def getSpdGuidVersion(spdFile):
107
108 spd = xml.dom.minidom.parse(inWorkspace(spdFile))
109
110 return (XmlElement(spd, "/PackageSurfaceArea/SpdHeader/GuidValue"),
111 XmlElement(spd, "/PackageSurfaceArea/SpdHeader/Version"))
112
113 def makeFar(files, farname):
114
115 domImpl = xml.dom.minidom.getDOMImplementation()
116 man = domImpl.createDocument(None, "FrameworkArchiveManifest", None)
117 top_element = man.documentElement
118
119 top_element.appendChild(makeFarHeader(man))
120
121 packList = man.createElement("FarPackageList")
122 top_element.appendChild(packList)
123
124 platList = man.createElement("FarPlatformList")
125 top_element.appendChild(platList)
126
127 contents = man.createElement("Contents")
128 top_element.appendChild(contents)
129
130 exts = man.createElement("UserExtensions")
131 top_element.appendChild(exts)
132
133 zip = zipfile.ZipFile(farname, "w")
134 for infile in set(files):
135 if not os.path.exists(inWorkspace(infile)):
136 print "Skipping non-existent file '%s'." % infile
137 (_, extension) = os.path.splitext(infile)
138 if extension == ".spd":
139 filelist = parseSpd(infile)
140 spdDir = os.path.dirname(infile)
141
142 (spdGuid, spdVersion) = getSpdGuidVersion(infile)
143
144 package = man.createElement("FarPackage")
145 packList.appendChild(package)
146
147 spdfilename = farFileNode(man, inWorkspace(infile))
148 zip.write(inWorkspace(infile), infile)
149 spdfilename.appendChild(man.createTextNode(lean(infile)))
150 package.appendChild(spdfilename)
151
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)
172
173 for spdfile in filelist:
174 content = farFileNode(man, inWorkspace(os.path.join(spdDir, spdfile)))
175 zip.write(inWorkspace(os.path.join(spdDir, spdfile)), spdfile)
176 content.appendChild(man.createTextNode(lean(spdfile)))
177 packContents.appendChild(content)
178
179 elif extension == ".fpd":
180
181 platform = man.createElement("FarPlatform")
182 platList.appendChild(platform)
183
184 fpdfilename = farFileNode(man, inWorkspace(infile))
185 zip.write(inWorkspace(infile), infile)
186 platform.appendChild(fpdfilename)
187 fpdfilename.appendChild(man.createTextNode(lean(infile)))
188
189 else:
190 content = farFileNode(man, inWorkspace(infile))
191 zip.write(inWorkspace(infile), infile)
192 content.appendChild(man.createTextNode(lean(infile)))
193 contents.appendChild(content)
194
195 zip.writestr("FrameworkArchiveManifest.xml", man.toprettyxml(2*" "))
196 zip.close()
197 return
198
199 def 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
206 # This acts like the main() function for the script, unless it is 'import'ed
207 # into another script.
208 if __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.
214 optlist, args = getopt.getopt(sys.argv[1:], 'hf:t:', [ 'template=', 'far=', 'help'])
215
216 # First pass through the options list.
217 for o, a in optlist:
218 if o in ["-h", "--help"]:
219 print """
220 Pass a list of .spd and .fpd files to be placed into a far for distribution.
221 You 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
225 The file paths of .spd and .fpd are treated as relative to the WORKSPACE
226 environment variable which must be set to a valid workspace root directory.
227 """ % os.path.basename(sys.argv[0])
228
229 sys.exit()
230 optlist.remove((o,a))
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)
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
241 if o in ["-f", "--far"]:
242 far.FileName = a
243
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)