/[ascend]/trunk/mac/install-gtk.py
ViewVC logotype

Contents of /trunk/mac/install-gtk.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2154 - (show annotations) (download) (as text)
Tue Mar 2 07:32:13 2010 UTC (10 years, 10 months ago) by jpye
File MIME type: text/x-python
File size: 6615 byte(s)
Move installgtk to mac directory.
1 #!/usr/bin/env python
2 # SCons support for bundled GTK installation
3 # Written by John Pye, Nov 2009
4
5
6 """
7 This tool installs the necessary files to allow GTK to run in a standalone
8 installation.
9
10 This approach is suitable for Mac (and maybe for Windows too) where we often
11 must assume that GTK+ is not separately installed on the system, or can't assume
12 that the version will be compatible.
13
14 Ultimately, it would be desirable for a Mac 'framework' to be utilised for this
15 purpose, but that option is not yet available.
16
17 Currently, this tool is a command-line thing that you must run after ASCEND
18 has been compiled, but before you run 'scons install'. It will copy all the
19 necessary files into dist/PyGTK.bundle; these files will then be copied by SCons
20 into their files (.dmg preparation folder) location.
21 """
22
23 import os.path
24 import glob
25 import subprocess, sys, os.path, re, shutil
26 from distutils.dir_util import copy_tree
27
28 otool_re = re.compile(r"""\s+(.+)\s\(compatibility version (.*), current version (.*)\)""")
29
30 def find_deps(binary):
31 deps = set()
32 P = subprocess.Popen(['/usr/bin/otool','-L',binary],stdout=subprocess.PIPE)
33 O = P.communicate()[0].strip()
34 for o in O.split("\n")[1:]:
35 m = otool_re.match(o)
36 #print " -->",m.group(1)
37 deps.add(m.group(1))
38 return deps
39
40 def reroute_deps(lib,gtksite,pysite,orig):
41 deps = find_deps(lib)
42 lib_is_gtk = (os.path.commonprefix([gtksite,orig]) == gtksite)
43 lib_is_py = (os.path.commonprefix([pysite,orig]) == pysite)
44 if lib_is_py:
45 print "LIB %s IS PY" % orig
46 if lib_is_gtk:
47 print "LIB %s IS GTK" % orig
48
49 rpath_used = False
50 for d in deps:
51 oldpath = d
52 r = os.path.commonprefix([oldpath,gtksite])
53 if r == gtksite:
54 # this dependency is pointing into the GTK installation location
55 dir, f = os.path.split(oldpath)
56 if lib_is_gtk:
57 newpath = "@loader_path/"+f
58 elif lib_is_py:
59 # construct relative path from python lib to GTK libs
60 uplevels = 1
61 rel = orig[len(os.path.commonprefix([pysite,orig])):]
62 print "RELPATH = ",rel
63 dir1,tail = os.path.split(rel)
64 while dir1:
65 uplevels += 1
66 dir1, tail = os.path.split(dir1)
67 newpath = "@loader_path" + ("/.."*uplevels) + "/lib/" + f
68 else:
69 r = os.path.commonprefix([oldpath,pysite])
70 if r == pysite:
71 # this dependency is pointing to a file installed inside Python
72 newpath = "python/" + oldpath[len(r):]
73 else:
74 continue
75
76 cmd = ['/usr/bin/install_name_tool','-change',oldpath,newpath,lib]
77 print "RELINK %s: %s --> %s" % (lib,oldpath,newpath)
78 #print " ".join(cmd)
79 P = subprocess.Popen(cmd,stdout=subprocess.PIPE)
80 P.communicate()
81 rpath_used = True
82
83 def find_and_replace(fname, pattern, replace):
84 t = open(fname).read()
85 t1 = pattern.sub(replace,t)
86 f = open(fname,'w')
87 f.write(t1)
88 f.close()
89
90 if __name__ == "__main__":
91 import modulefinder
92 M = modulefinder.ModuleFinder()
93 sys.path.append("..")
94 script = os.path.normpath(os.path.join(sys.path[0],"../pygtk/gtkbrowser.py"))
95 M.run_script(script)
96
97 pysite="/Library/Python/2.5/site-packages/"
98 if pysite[-1:]!="/":
99 raise RuntimeError("missing trailing slash in pysite")
100
101 gtksite = os.path.expanduser("~/gtk/inst/")
102 if gtksite[-1:]!="/":
103 raise RuntimeError("missing trailing slash in gtksite")
104
105 imports = set()
106 ignore_paths = ['/System/Library/Frameworks/Python.framework'
107 ,'/System/Library/Frameworks/Carbon.framework'
108 ,'/System/Library/Frameworks/Cocoa.framework'
109 ,'/usr/lib'
110 ,os.path.dirname(script)]
111 for name, m in M.modules.items():
112 if not m.__file__:
113 continue
114 ok = True
115 for i in ignore_paths:
116 if os.path.commonprefix([i,m.__file__]) == i:
117 ok = False
118 if ok is False:
119 continue
120
121 imports.add(m)
122 print m
123
124 print "\n\nChecking otool deps"
125
126 files = set()
127 pyfiles = set()
128 for m in imports:
129 files.add(m.__file__)
130
131 if m.__file__[-3:] == ".so":
132 print "FILE:",m.__file__
133 files |= find_deps(m.__file__)
134
135 elif m.__file__[-3:] == ".py":
136 print "PY:",m.__file__
137 pyfiles.add(m.__file__)
138
139 print "\n\nOTOOL DEPS"
140 for f in files:
141 if f[-3:] != ".py":
142 print f
143
144 print "\nAdd pixbuf loaders to list..."
145 loaders = glob.glob(gtksite+"lib/gtk-2.0/*/loaders/libpixbufloader-*.so")
146 for l in loaders:
147 print l
148 files.add(l)
149
150 print "\n\nFinding all GTK libs in the list"
151 gtkimports = set()
152 for f in files:
153 if os.path.commonprefix([gtksite,f]) == gtksite:
154 gtkimports.add(f)
155 print f
156
157 print "\n\nFinding all Python site-packages stuff in the list"
158 pyimports = set()
159 for f in files:
160 if os.path.commonprefix([pysite,f]) == pysite:
161 pyimports.add(f)
162 print f
163
164 # define the paths into which we'll copy all the stuff
165 distpath = os.path.normpath(os.path.join(sys.path[0],"../dist"))
166 targetpath = os.path.join(distpath,"PyGTK.bundle")
167 pytarget = os.path.join(targetpath,"python")
168 gtktarget = targetpath
169 gtklibtarget = os.path.join(gtktarget,"lib")
170
171 print "\n\nCopying all Python files into our bundle"
172 for f in pyfiles | pyimports:
173 if not os.path.commonprefix([f,pysite]) == pysite:
174 raise RuntimeError("Unknown python import '%s' in list" % f)
175 r = f[len(pysite):]
176 dir, f1 = os.path.split(r)
177 if not os.path.exists(os.path.join(pytarget,dir)):
178 os.makedirs(os.path.join(pytarget,dir))
179 print r
180 dest = os.path.join(pytarget,r)
181 shutil.copy(f, dest)
182 if dest[-3:] == ".so":
183 print " rerouting dependencies..."
184 reroute_deps(dest,gtksite,pysite,orig=f)
185
186 print "\n\nCopy all GTK libs into our bundle"
187 if not os.path.exists(gtklibtarget):
188 os.makedirs(gtklibtarget)
189 for f in gtkimports:
190 if not os.path.commonprefix([f, gtksite]) == gtksite:
191 raise RuntimeError("Unknown gtk import in list")
192 r = f[len(gtksite):]
193 dir, f1 = os.path.split(r)
194 dest = os.path.join(gtklibtarget, f1)
195 print dest
196 shutil.copy(f, dest)
197 reroute_deps(dest,gtksite,pysite,orig=f)
198
199 print "\nCopying GTK related files"
200 reldirs = ["etc/gtk-2.0", "etc/pango", "etc/fonts"]
201 for d in reldirs:
202 print "%s --> %s" % (os.path.join(gtksite,d),os.path.join(gtktarget,d))
203 copy_tree(os.path.join(gtksite,d),os.path.join(gtktarget,d))
204
205 print "\nFixing pixbuf loader paths"
206 loaderre = re.compile("%slib/gtk-2\\.0/[^/]+/loaders/" % re.escape(gtksite))
207 find_and_replace("%s/etc/gtk-2.0/gdk-pixbuf.loaders"%gtktarget,loaderre,"@loader_path/")
208
209 print "\nFixing absolute path sin GTK etc files"
210 etcfiles = ["%s/etc/%s" % (gtktarget, f) for f in
211 ['gtk-2.0/gtk.immodules', 'pango/pango.modules'] #'pango/pangorc',
212 ]
213 etcre = re.compile("%s"%re.escape(gtksite))
214 for e in etcfiles:
215 print e
216
217 print "\nTODO: copy localisation files (not yet implemented)"
218 #SHARE=`echo $PREFIX/share/locale/*/LC_MESSAGES/gimp*`
219
220
221
222
223

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22