Mercurial > mxe-octave
comparison tools/pkg-install.py @ 4067:bdcddfdc57d0
Install binary of-* packages
* Makefile.in: (OCTAVE_FORGE_PKG_BUILD) call pkg-install.py if building binary packages
* src/of-io-1-cross-fixes.patch: new patch
* src/of-specfun-1-cross-fixes.patch: new patch
* tools/pkg-install.py: new file
author | John Donoghue <john.donoghue@ieee.org> |
---|---|
date | Sat, 26 Dec 2015 22:00:59 -0500 |
parents | |
children | fc806c8583a9 |
comparison
equal
deleted
inserted
replaced
4066:0962acdde3be | 4067:bdcddfdc57d0 |
---|---|
1 #!/usr/bin/python | |
2 import sys | |
3 import os | |
4 import re | |
5 import tempfile | |
6 import shutil | |
7 import fnmatch | |
8 import subprocess | |
9 | |
10 class Env: | |
11 mkoctfile = "mkoctfile"; | |
12 octave_config = "octave-config"; | |
13 make = "make" | |
14 verbose = True; | |
15 prefix = "" | |
16 pkg = "" | |
17 arch = "" | |
18 tmp = "/tmp" | |
19 apiversion = "" | |
20 bin_dir = "" | |
21 m_dir = "" | |
22 arch_dir = "" | |
23 config_opts = "" | |
24 | |
25 def show_usage(): | |
26 print sys.argv(0), "[options] pkg1 [pkg2]" | |
27 | |
28 def verify_directory(dirname): | |
29 for f in [ "COPYING", "DESCRIPTION" ]: | |
30 if os.path.isfile(dirname + "/" + f) == False: | |
31 raise Exception, "package is missing file " + f | |
32 | |
33 def get_description(descfile): | |
34 with open(descfile, 'r') as f: | |
35 lines = f.read().splitlines() | |
36 d = dict(s.split(': ',1) for s in lines if s.find(': ') != -1) | |
37 return d | |
38 | |
39 def extract_pkg(filename, nm): | |
40 pkg = [] | |
41 with open(filename, 'r') as f: | |
42 lines = f.read().splitlines() | |
43 for l in lines: | |
44 so = re.search(nm, l, re.M|re.S) | |
45 if so: | |
46 pkg.append(str(so.group(1))) | |
47 return pkg | |
48 | |
49 def write_index_file(env, desc, index_nm): | |
50 | |
51 with open(index_nm, 'w') as f: | |
52 files = os.listdir(env.m_dir) | |
53 classes = fnmatch.filter(files, "@*") | |
54 | |
55 # check classes | |
56 for c in classes: | |
57 class_name = c | |
58 class_path = env.m_dir + "/" + c; | |
59 if os.path.isdir(class_path) == True: | |
60 class_files = list(class_name + "/" + a for a in os.listdir(class_path)) | |
61 files += class_files | |
62 | |
63 # arch dependant | |
64 if os.path.exists(env.arch_dir) == True: | |
65 archfiles = os.listdir(env.arch_dir) | |
66 files += archfiles | |
67 | |
68 functions = [] | |
69 for a in files: | |
70 if a.endswith(".m"): | |
71 functions.append( str(a[0:len(a)-2]) ) | |
72 elif a.endswith(".oct"): | |
73 functions.append( str(a[0:len(a)-4]) ) | |
74 | |
75 f.write(env.pkg + " >> " + desc['Title'] + "\n"); | |
76 f.write(desc['Categories'].replace(",", " ") + "\n") | |
77 for a in functions: | |
78 f.write(" " + a + "\n") | |
79 | |
80 def finish_installation(env, packdir): | |
81 # octave would run post_install.m here - instead we will copy the post_install.m | |
82 # somewhere and then on initial startup, run the post_install | |
83 if os.path.isfile(packdir + "/post_install.m") == True: | |
84 if env.verbose: | |
85 print "Copying .. post_install.m" | |
86 destdir = env.prefix + "/share/octave/site/m/once_only" | |
87 if os.path.exists(destdir) == False: | |
88 os.makedirs(destdir) | |
89 shutil.copy2(packdir + "/post_install.m", destdir + "/" + env.pkg + "-post_install.m") | |
90 | |
91 def create_pkgadddel (env, packdir, nm): | |
92 if env.verbose: | |
93 print "Creating...", nm | |
94 | |
95 instfid = open(env.m_dir + "/" + nm, "w") | |
96 if os.path.exists(env.arch_dir) == True: | |
97 archfid = open(env.arch_dir + "/" + nm, "w") | |
98 else: | |
99 archfid = instfid | |
100 | |
101 # search inst .m files for PKG_ commands | |
102 instdir = packdir + "/inst" | |
103 files = list(instdir + "/" + a for a in os.listdir(instdir)) | |
104 m_files = fnmatch.filter(files, "*.m") | |
105 for f in m_files: | |
106 for a in extract_pkg(f, '^[#%][#%]* *' + nm + ': *(.*)$'): | |
107 instfid.write("%s\n" % str(a)) | |
108 | |
109 # search inst .m files for PKG_ commands | |
110 if os.path.exists(packdir + "/src") == True: | |
111 srcdir = packdir + "/src" | |
112 files = list(srcdir + "/" + a for a in os.listdir(srcdir)) | |
113 c_files = fnmatch.filter(files, "*.cc") | |
114 for f in c_files: | |
115 for a in extract_pkg(f, '^//* *' + nm + ': *(.*)$'): | |
116 archfid.write("%s\n" % str(a)) | |
117 for a in extract_pkg(f, '^/\** *' + nm + ': *(.*) *\*/$'): | |
118 archfid.write("%s\n" % a) | |
119 | |
120 # add PKG_XXX from packdir if exists | |
121 if os.path.isfile(packdir + "/" + nm) == True: | |
122 with open(packdir + "/" + nm, 'r') as f: | |
123 lines = f.read().splitlines() | |
124 for a in lines: | |
125 archfid.write("%s\n" % a) | |
126 | |
127 # close files | |
128 if archfid != instfid: | |
129 archfid.close() | |
130 if os.stat(env.arch_dir + "/" + nm).st_size == 0: | |
131 os.remove(env.arch_dir + "/" + nm) | |
132 instfid.close() | |
133 if os.stat(env.m_dir + "/" + nm).st_size == 0: | |
134 os.remove(env.m_dir + "/" + nm) | |
135 | |
136 def generate_lookfor_cache (env): | |
137 # TODO create doc-cache | |
138 pass | |
139 | |
140 def copyfile(files, destdir): | |
141 if os.path.exists(destdir) == False: | |
142 os.mkdir(destdir) | |
143 for a in files: | |
144 if os.path.isfile(a): | |
145 shutil.copy2(a, destdir) | |
146 if os.path.isdir(a): | |
147 name= os.path.basename(a) | |
148 morefiles=(a + "/" + b for b in os.listdir(a)) | |
149 copyfile(morefiles, destdir + "/" + name) | |
150 | |
151 def copy_files(env, pkgdir): | |
152 if os.path.exists(env.m_dir) == False: | |
153 os.makedirs(env.m_dir) | |
154 instdir = pkgdir + "/inst" | |
155 | |
156 if env.verbose: | |
157 print "Copying m files ..." | |
158 | |
159 files = list(instdir + "/" + a for a in os.listdir(instdir)) | |
160 # filter for arch folder | |
161 if os.path.exists(instdir + "/" + env.arch) == True: | |
162 files.remove(instdir + "/" + env.arch) | |
163 | |
164 copyfile(files, env.m_dir) | |
165 | |
166 if os.path.exists(instdir + "/" + env.arch) == True: | |
167 if env.verbose: | |
168 print "Copying arch files ..." | |
169 files = list(instdir + "/" + env.arch + "/" + a for a in os.listdir(instdir + "/" + env.arch)) | |
170 if len(files) > 0: | |
171 if os.path.exists(env.arch_dir) == False: | |
172 os.makedirs(env.arch_dir) | |
173 copyfile(files, env.arch_dir) | |
174 shutil.rmtree(instdir + "/" + env.arch) | |
175 | |
176 # packinfo | |
177 if env.verbose: | |
178 print "Copying packinfo files ..." | |
179 if os.path.exists(env.m_dir + "/packinfo") == False: | |
180 os.makedirs(env.m_dir + "/packinfo") | |
181 copyfile([pkgdir + "/DESCRIPTION"], env.m_dir + "/packinfo") | |
182 copyfile([pkgdir + "/COPYING"], env.m_dir + "/packinfo") | |
183 copyfile([pkgdir + "/CITATION"], env.m_dir + "/packinfo") | |
184 copyfile([pkgdir + "/NEWS"], env.m_dir + "/packinfo") | |
185 copyfile([pkgdir + "/ONEWS"], env.m_dir + "/packinfo") | |
186 copyfile([pkgdir + "/ChangeLog"], env.m_dir + "/packinfo") | |
187 | |
188 # index file | |
189 if env.verbose: | |
190 print "Copying/creating INDEX ..." | |
191 if os.path.isfile(pkgdir + "/INDEX") == True: | |
192 copyfile([pkgdir + "/INDEX"], env.m_dir + "/packinfo") | |
193 else: | |
194 desc = get_description(pkgdir + "/DESCRIPTION") | |
195 write_index_file(env, desc, env.m_dir + "/packinfo/INDEX") | |
196 | |
197 copyfile([pkgdir + "on_uninstall.m"], env.m_dir + "/packinfo") | |
198 | |
199 # doc dir ? | |
200 docdir = pkgdir + "/doc" | |
201 if os.path.exists(docdir) == True: | |
202 if env.verbose: | |
203 print "Copying doc files ..." | |
204 files = (docdir + "/" + a for a in os.listdir(docdir)) | |
205 copyfile(files, env.m_dir + "/doc") | |
206 | |
207 # bin dir ? | |
208 bindir = pkgdir + "/bin" | |
209 if os.path.exists(bindir) == True: | |
210 if env.verbose: | |
211 print "Copying bin files ..." | |
212 files = (bindir + "/" + a for a in os.listdir(bindir)) | |
213 copyfile(files, env.m_dir + "/bin") | |
214 | |
215 def configure_make(env, packdir): | |
216 if os.path.isdir(packdir + "/inst") == False: | |
217 os.mkdir(packdir + "/inst") | |
218 | |
219 if os.path.isdir(packdir + "/src") == True: | |
220 src = packdir + "/src" | |
221 os.chdir(src) | |
222 | |
223 if os.path.isfile(src + "/configure") == True: | |
224 if env.verbose: | |
225 print "running ./configure " + env.config_opts | |
226 | |
227 os.system("./configure " + env.config_opts + "") | |
228 | |
229 if os.path.isfile(src + "/Makefile") == True: | |
230 if env.verbose: | |
231 print "running make ..." | |
232 if os.system(env.make + " --directory '" + src + "'" ) != 0: | |
233 raise Exception, "make failed during build - stopping install" | |
234 | |
235 # copy files to inst and inst arch | |
236 files = src + "/FILES" | |
237 instdir = packdir + "/inst" | |
238 archdir = instdir + "/" + env.arch | |
239 | |
240 if os.path.isfile(files) == True: | |
241 pass # TODO yet | |
242 else: | |
243 # get .m, .oct and .mex files | |
244 files = os.listdir(src) | |
245 m_files = fnmatch.filter(files, "*.m") | |
246 mex_files = fnmatch.filter(files, "*.mex") | |
247 oct_files = fnmatch.filter(files, "*.oct") | |
248 files = m_files + mex_files + oct_files | |
249 files = list(src + "/" + s for s in files) | |
250 | |
251 # split files into arch and non arch files | |
252 archdependant = fnmatch.filter(files, "*.mex") + fnmatch.filter(files,"*.oct") | |
253 archindependant = list( x for x in files if x not in archdependant ) | |
254 | |
255 # copy the files | |
256 copyfile(archindependant, instdir) | |
257 copyfile(archdependant, archdir) | |
258 | |
259 def add_package_list(env, desc): | |
260 #pkglist = env.prefix + "/share/octave/octave_packages" | |
261 #with open(pkglist, 'r') as f: | |
262 # lines = f.read().splitlines() | |
263 # currently doing nothing for adding, will let installer do | |
264 pass | |
265 | |
266 def uninstall_pkg(pkg,env): | |
267 pass | |
268 | |
269 def install_pkg(pkg, env): | |
270 pkg = os.path.abspath(pkg) | |
271 currdir = os.getcwd() | |
272 | |
273 try: | |
274 ## Check that the directory in prefix exist. If it doesn't: create it! | |
275 tmpdir = tempfile.mkdtemp("-pkg","tmp", env.tmp) | |
276 os.chdir(tmpdir) | |
277 | |
278 # unpack dir | |
279 if env.verbose: | |
280 os.system("tar xzvf '" + pkg + "'") | |
281 else: | |
282 os.system("tar xzf '" + pkg + "'") | |
283 | |
284 # get list for files creates | |
285 files=os.listdir(tmpdir) | |
286 if len(files) != 1: | |
287 print "Expected to unpack to only one directory" | |
288 | |
289 packdir = os.path.abspath(files[0]) | |
290 | |
291 # verify have expected min files | |
292 verify_directory(packdir) | |
293 | |
294 # read the description file | |
295 desc = get_description(packdir + "/DESCRIPTION") | |
296 | |
297 # make the path names | |
298 env.pkg = desc['Name'].lower() | |
299 env.m_dir = env.prefix + "/share/octave/packages/" + env.pkg + "-" + desc['Version']; | |
300 env.arch_dir = env.prefix + "/lib/octave/packages/" + env.pkg + "-" + desc['Version'] + "/" + env.arch + "-" + env.apiversion | |
301 | |
302 configure_make (env, packdir) | |
303 | |
304 # install package files | |
305 copy_files(env, packdir) | |
306 create_pkgadddel (env, packdir, "PKG_ADD"); | |
307 create_pkgadddel (env, packdir, "PKG_DEL"); | |
308 finish_installation(env, packdir) | |
309 generate_lookfor_cache (env); | |
310 | |
311 # update package list | |
312 add_package_list(env, desc) | |
313 finally: | |
314 if env.verbose: | |
315 print "cleaning up" | |
316 os.chdir(currdir) | |
317 shutil.rmtree(tmpdir) | |
318 | |
319 | |
320 def pkg (args): | |
321 arch = '' | |
322 | |
323 env = Env() | |
324 | |
325 files = [] | |
326 | |
327 for a in args: | |
328 print a | |
329 c=a.split("=") | |
330 key=c[0] | |
331 if len(c) > 1: | |
332 val=c[1] | |
333 else: | |
334 val="" | |
335 | |
336 if key == "-verbose": | |
337 env.verbose = True; | |
338 elif key == "--verbose": | |
339 env.verbose = True; | |
340 elif val == "": | |
341 files.append(key) | |
342 | |
343 | |
344 if os.environ.get("OCTAVE_CONFIG") != None: | |
345 env.octave_config = os.environ["OCTAVE_CONFIG"] | |
346 if os.environ.get("MAKE") != None: | |
347 env.make = os.environ["MAKE"] | |
348 if os.environ.get("MKOCTFILE") != None: | |
349 env.mkoctfile = os.environ["MKOCTFILE"] | |
350 if os.environ.get("TMP") != None: | |
351 env.tmp = os.environ["TMP"] | |
352 | |
353 if env.verbose: | |
354 env.mkoctfile = env.mkoctfile + " --verbose" | |
355 | |
356 # make sure we have these set up in env | |
357 os.environ['OCTAVE_CONFIG'] = env.octave_config; | |
358 os.environ['MAKE'] = env.make; | |
359 os.environ['MKOCTFILE'] = env.mkoctfile; | |
360 os.environ['TMP'] = env.tmp; | |
361 os.environ['OCTAVE'] = 'echo'; | |
362 | |
363 if os.environ.get("CC") == None: | |
364 os.environ['CC'] = os.popen(env.mkoctfile + " -p CC").read().rstrip("\r\n") | |
365 if os.environ.get("CXX") == None: | |
366 os.environ['CXX'] = os.popen(env.mkoctfile + " -p CXX").read().rstrip("\r\n") | |
367 if os.environ.get("AR") == None: | |
368 os.environ['AR'] = os.popen(env.mkoctfile + " -p AR").read().rstrip("\r\n") | |
369 if os.environ.get("RANLIB") == None: | |
370 os.environ['RANLIB'] = os.popen(env.mkoctfile + " -p RANLIB").read().rstrip("\r\n") | |
371 | |
372 if os.environ.get("CONFIGURE_OPTIONS") != None: | |
373 env.config_opts = os.environ['CONFIGURE_OPTIONS'] | |
374 | |
375 # work out what arch is etc from mkoctfile/config | |
376 if env.prefix == "": | |
377 env.prefix = os.popen(env.octave_config + " -p PREFIX").read().rstrip("\r\n") | |
378 | |
379 env.arch = os.popen(env.octave_config + " -p CANONICAL_HOST_TYPE").read().rstrip("\r\n") | |
380 env.apiversion = os.popen(env.octave_config + " -p API_VERSION").read().rstrip("\r\n") | |
381 env.bindir = os.popen(env.octave_config + " -p BINDIR").read().rstrip("\r\n") | |
382 | |
383 if env.verbose: | |
384 print "mkoctfile=", env.mkoctfile | |
385 print "arch=", env.arch | |
386 print "apiversion=", env.apiversion | |
387 print "prefix=", env.prefix | |
388 print "files=", files | |
389 print "verbose=", env.verbose | |
390 | |
391 for a in files: | |
392 install_pkg(a, env) | |
393 | |
394 return 0 | |
395 | |
396 if __name__ == "__main__": | |
397 if len(sys.argv) > 1: | |
398 pkg(sys.argv[1:]) | |
399 else: | |
400 show_usage() |