##// END OF EJS Templates
add --pure flag to setup.py...
Martin Geisler -
r7722:103127a8 default
parent child Browse files
Show More
@@ -1,218 +1,247
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 #
2 #
3 # This is the mercurial setup script.
3 # This is the mercurial setup script.
4 #
4 #
5 # 'python setup.py install', or
5 # 'python setup.py install', or
6 # 'python setup.py --help' for more options
6 # 'python setup.py --help' for more options
7
7
8 import sys
8 import sys
9 if not hasattr(sys, 'version_info') or sys.version_info < (2, 3, 0, 'final'):
9 if not hasattr(sys, 'version_info') or sys.version_info < (2, 3, 0, 'final'):
10 raise SystemExit("Mercurial requires python 2.3 or later.")
10 raise SystemExit("Mercurial requires python 2.3 or later.")
11
11
12 # Solaris Python packaging brain damage
12 # Solaris Python packaging brain damage
13 try:
13 try:
14 import hashlib
14 import hashlib
15 sha = hashlib.sha1()
15 sha = hashlib.sha1()
16 except:
16 except:
17 try:
17 try:
18 import sha
18 import sha
19 except:
19 except:
20 raise SystemExit(
20 raise SystemExit(
21 "Couldn't import standard hashlib (incomplete Python install).")
21 "Couldn't import standard hashlib (incomplete Python install).")
22
22
23 try:
23 try:
24 import zlib
24 import zlib
25 except:
25 except:
26 raise SystemExit(
26 raise SystemExit(
27 "Couldn't import standard zlib (incomplete Python install).")
27 "Couldn't import standard zlib (incomplete Python install).")
28
28
29 import os, time
29 import os, time
30 import shutil
30 import shutil
31 import tempfile
31 import tempfile
32 from distutils.core import setup, Extension
32 from distutils.core import setup, Extension
33 from distutils.dist import Distribution
33 from distutils.command.install_data import install_data
34 from distutils.command.install_data import install_data
34 from distutils.command.build import build
35 from distutils.command.build import build
36 from distutils.command.build_py import build_py
35 from distutils.spawn import spawn, find_executable
37 from distutils.spawn import spawn, find_executable
36 from distutils.ccompiler import new_compiler
38 from distutils.ccompiler import new_compiler
37
39
38 extra = {}
40 extra = {}
39 scripts = ['hg']
41 scripts = ['hg']
40 if os.name == 'nt':
42 if os.name == 'nt':
41 scripts.append('contrib/win32/hg.bat')
43 scripts.append('contrib/win32/hg.bat')
42
44
43 # simplified version of distutils.ccompiler.CCompiler.has_function
45 # simplified version of distutils.ccompiler.CCompiler.has_function
44 # that actually removes its temporary files.
46 # that actually removes its temporary files.
45 def has_function(cc, funcname):
47 def has_function(cc, funcname):
46 tmpdir = tempfile.mkdtemp(prefix='hg-install-')
48 tmpdir = tempfile.mkdtemp(prefix='hg-install-')
47 devnull = oldstderr = None
49 devnull = oldstderr = None
48 try:
50 try:
49 try:
51 try:
50 fname = os.path.join(tmpdir, 'funcname.c')
52 fname = os.path.join(tmpdir, 'funcname.c')
51 f = open(fname, 'w')
53 f = open(fname, 'w')
52 f.write('int main(void) {\n')
54 f.write('int main(void) {\n')
53 f.write(' %s();\n' % funcname)
55 f.write(' %s();\n' % funcname)
54 f.write('}\n')
56 f.write('}\n')
55 f.close()
57 f.close()
56 # Redirect stderr to /dev/null to hide any error messages
58 # Redirect stderr to /dev/null to hide any error messages
57 # from the compiler.
59 # from the compiler.
58 # This will have to be changed if we ever have to check
60 # This will have to be changed if we ever have to check
59 # for a function on Windows.
61 # for a function on Windows.
60 devnull = open('/dev/null', 'w')
62 devnull = open('/dev/null', 'w')
61 oldstderr = os.dup(sys.stderr.fileno())
63 oldstderr = os.dup(sys.stderr.fileno())
62 os.dup2(devnull.fileno(), sys.stderr.fileno())
64 os.dup2(devnull.fileno(), sys.stderr.fileno())
63 objects = cc.compile([fname])
65 objects = cc.compile([fname])
64 cc.link_executable(objects, os.path.join(tmpdir, "a.out"))
66 cc.link_executable(objects, os.path.join(tmpdir, "a.out"))
65 except:
67 except:
66 return False
68 return False
67 return True
69 return True
68 finally:
70 finally:
69 if oldstderr is not None:
71 if oldstderr is not None:
70 os.dup2(oldstderr, sys.stderr.fileno())
72 os.dup2(oldstderr, sys.stderr.fileno())
71 if devnull is not None:
73 if devnull is not None:
72 devnull.close()
74 devnull.close()
73 shutil.rmtree(tmpdir)
75 shutil.rmtree(tmpdir)
74
76
75 # py2exe needs to be installed to work
77 # py2exe needs to be installed to work
76 try:
78 try:
77 import py2exe
79 import py2exe
78
80
79 # Help py2exe to find win32com.shell
81 # Help py2exe to find win32com.shell
80 try:
82 try:
81 import modulefinder
83 import modulefinder
82 import win32com
84 import win32com
83 for p in win32com.__path__[1:]: # Take the path to win32comext
85 for p in win32com.__path__[1:]: # Take the path to win32comext
84 modulefinder.AddPackagePath("win32com", p)
86 modulefinder.AddPackagePath("win32com", p)
85 pn = "win32com.shell"
87 pn = "win32com.shell"
86 __import__(pn)
88 __import__(pn)
87 m = sys.modules[pn]
89 m = sys.modules[pn]
88 for p in m.__path__[1:]:
90 for p in m.__path__[1:]:
89 modulefinder.AddPackagePath(pn, p)
91 modulefinder.AddPackagePath(pn, p)
90 except ImportError:
92 except ImportError:
91 pass
93 pass
92
94
93 extra['console'] = ['hg']
95 extra['console'] = ['hg']
94
96
95 except ImportError:
97 except ImportError:
96 pass
98 pass
97
99
98 try:
100 try:
99 # execute hg out of this directory with a custom environment which
101 # execute hg out of this directory with a custom environment which
100 # includes the pure Python modules in mercurial/pure
102 # includes the pure Python modules in mercurial/pure
101 pypath = os.environ.get('PYTHONPATH', '')
103 pypath = os.environ.get('PYTHONPATH', '')
102 purepath = os.path.join('mercurial', 'pure')
104 purepath = os.path.join('mercurial', 'pure')
103 os.environ['PYTHONPATH'] = os.pathsep.join(['mercurial', purepath, pypath])
105 os.environ['PYTHONPATH'] = os.pathsep.join(['mercurial', purepath, pypath])
104 cmd = '%s id -it' % os.path.join('.', 'hg')
106 cmd = '%s id -it' % os.path.join('.', 'hg')
105 l = os.popen(cmd).read().split()
107 l = os.popen(cmd).read().split()
106 os.environ['PYTHONPATH'] = pypath
108 os.environ['PYTHONPATH'] = pypath
107 while len(l) > 1 and l[-1][0].isalpha(): # remove non-numbered tags
109 while len(l) > 1 and l[-1][0].isalpha(): # remove non-numbered tags
108 l.pop()
110 l.pop()
109 version = l and l[-1] or 'unknown' # latest tag or revision number
111 version = l and l[-1] or 'unknown' # latest tag or revision number
110 if version.endswith('+'):
112 if version.endswith('+'):
111 version += time.strftime('%Y%m%d')
113 version += time.strftime('%Y%m%d')
112
114
113 except OSError:
115 except OSError:
114 version = "unknown"
116 version = "unknown"
115
117
116 f = file("mercurial/__version__.py", "w")
118 f = file("mercurial/__version__.py", "w")
117 f.write('# this file is autogenerated by setup.py\n')
119 f.write('# this file is autogenerated by setup.py\n')
118 f.write('version = "%s"\n' % version)
120 f.write('version = "%s"\n' % version)
119 f.close()
121 f.close()
120
122
121 class install_package_data(install_data):
123 class install_package_data(install_data):
122 def finalize_options(self):
124 def finalize_options(self):
123 self.set_undefined_options('install',
125 self.set_undefined_options('install',
124 ('install_lib', 'install_dir'))
126 ('install_lib', 'install_dir'))
125 install_data.finalize_options(self)
127 install_data.finalize_options(self)
126
128
127 class build_mo(build):
129 class build_mo(build):
128
130
129 description = "build translations (.mo files)"
131 description = "build translations (.mo files)"
130
132
131 def run(self):
133 def run(self):
132 if not find_executable('msgfmt'):
134 if not find_executable('msgfmt'):
133 self.warn("could not find msgfmt executable, no translations "
135 self.warn("could not find msgfmt executable, no translations "
134 "will be built")
136 "will be built")
135 return
137 return
136
138
137 podir = 'i18n'
139 podir = 'i18n'
138 if not os.path.isdir(podir):
140 if not os.path.isdir(podir):
139 self.warn("could not find %s/ directory" % podir)
141 self.warn("could not find %s/ directory" % podir)
140 return
142 return
141
143
142 join = os.path.join
144 join = os.path.join
143 for po in os.listdir(podir):
145 for po in os.listdir(podir):
144 if not po.endswith('.po'):
146 if not po.endswith('.po'):
145 continue
147 continue
146 pofile = join(podir, po)
148 pofile = join(podir, po)
147 modir = join('locale', po[:-3], 'LC_MESSAGES')
149 modir = join('locale', po[:-3], 'LC_MESSAGES')
148 mofile = join(modir, 'hg.mo')
150 mofile = join(modir, 'hg.mo')
149 cmd = ['msgfmt', '-v', '-o', mofile, pofile]
151 cmd = ['msgfmt', '-v', '-o', mofile, pofile]
150 if sys.platform != 'sunos5':
152 if sys.platform != 'sunos5':
151 # msgfmt on Solaris does not know about -c
153 # msgfmt on Solaris does not know about -c
152 cmd.append('-c')
154 cmd.append('-c')
153 self.mkpath(modir)
155 self.mkpath(modir)
154 self.make_file([pofile], mofile, spawn, (cmd,))
156 self.make_file([pofile], mofile, spawn, (cmd,))
155 self.distribution.data_files.append((join('mercurial', modir),
157 self.distribution.data_files.append((join('mercurial', modir),
156 [mofile]))
158 [mofile]))
157
159
158 build.sub_commands.append(('build_mo', None))
160 build.sub_commands.append(('build_mo', None))
159
161
162 Distribution.pure = 0
163 Distribution.global_options.append(('pure', None, "use pure (slow) Python "
164 "code instead of C extensions"))
165
166 class hg_build_py(build_py):
167
168 def finalize_options(self):
169 build_py.finalize_options(self)
170
171 if self.distribution.pure:
172 if self.py_modules is None:
173 self.py_modules = []
174 for ext in self.distribution.ext_modules:
175 if ext.name.startswith("mercurial."):
176 self.py_modules.append("mercurial.pure.%s" % ext.name[10:])
177 self.distribution.ext_modules = []
178
179 def find_modules(self):
180 modules = build_py.find_modules(self)
181 for module in modules:
182 if module[0] == "mercurial.pure":
183 if module[1] != "__init__":
184 yield ("mercurial", module[1], module[2])
185 else:
186 yield module
187
160 cmdclass = {'install_data': install_package_data,
188 cmdclass = {'install_data': install_package_data,
161 'build_mo': build_mo}
189 'build_mo': build_mo,
190 'build_py': hg_build_py}
162
191
163 ext_modules=[
192 ext_modules=[
164 Extension('mercurial.base85', ['mercurial/base85.c']),
193 Extension('mercurial.base85', ['mercurial/base85.c']),
165 Extension('mercurial.bdiff', ['mercurial/bdiff.c']),
194 Extension('mercurial.bdiff', ['mercurial/bdiff.c']),
166 Extension('mercurial.diffhelpers', ['mercurial/diffhelpers.c']),
195 Extension('mercurial.diffhelpers', ['mercurial/diffhelpers.c']),
167 Extension('mercurial.mpatch', ['mercurial/mpatch.c']),
196 Extension('mercurial.mpatch', ['mercurial/mpatch.c']),
168 Extension('mercurial.parsers', ['mercurial/parsers.c']),
197 Extension('mercurial.parsers', ['mercurial/parsers.c']),
169 ]
198 ]
170
199
171 packages = ['mercurial', 'mercurial.hgweb', 'hgext', 'hgext.convert',
200 packages = ['mercurial', 'mercurial.hgweb', 'hgext', 'hgext.convert',
172 'hgext.highlight', 'hgext.zeroconf', ]
201 'hgext.highlight', 'hgext.zeroconf', ]
173
202
174 try:
203 try:
175 import msvcrt
204 import msvcrt
176 ext_modules.append(Extension('mercurial.osutil', ['mercurial/osutil.c']))
205 ext_modules.append(Extension('mercurial.osutil', ['mercurial/osutil.c']))
177 except ImportError:
206 except ImportError:
178 pass
207 pass
179
208
180 try:
209 try:
181 import posix
210 import posix
182 ext_modules.append(Extension('mercurial.osutil', ['mercurial/osutil.c']))
211 ext_modules.append(Extension('mercurial.osutil', ['mercurial/osutil.c']))
183
212
184 if sys.platform == 'linux2' and os.uname()[2] > '2.6':
213 if sys.platform == 'linux2' and os.uname()[2] > '2.6':
185 # The inotify extension is only usable with Linux 2.6 kernels.
214 # The inotify extension is only usable with Linux 2.6 kernels.
186 # You also need a reasonably recent C library.
215 # You also need a reasonably recent C library.
187 cc = new_compiler()
216 cc = new_compiler()
188 if has_function(cc, 'inotify_add_watch'):
217 if has_function(cc, 'inotify_add_watch'):
189 ext_modules.append(Extension('hgext.inotify.linux._inotify',
218 ext_modules.append(Extension('hgext.inotify.linux._inotify',
190 ['hgext/inotify/linux/_inotify.c']))
219 ['hgext/inotify/linux/_inotify.c']))
191 packages.extend(['hgext.inotify', 'hgext.inotify.linux'])
220 packages.extend(['hgext.inotify', 'hgext.inotify.linux'])
192 except ImportError:
221 except ImportError:
193 pass
222 pass
194
223
195 datafiles = []
224 datafiles = []
196 for root in ('templates', 'i18n'):
225 for root in ('templates', 'i18n'):
197 for dir, dirs, files in os.walk(root):
226 for dir, dirs, files in os.walk(root):
198 datafiles.append((os.path.join('mercurial', dir),
227 datafiles.append((os.path.join('mercurial', dir),
199 [os.path.join(dir, file_) for file_ in files]))
228 [os.path.join(dir, file_) for file_ in files]))
200
229
201 setup(name='mercurial',
230 setup(name='mercurial',
202 version=version,
231 version=version,
203 author='Matt Mackall',
232 author='Matt Mackall',
204 author_email='mpm@selenic.com',
233 author_email='mpm@selenic.com',
205 url='http://selenic.com/mercurial',
234 url='http://selenic.com/mercurial',
206 description='Scalable distributed SCM',
235 description='Scalable distributed SCM',
207 license='GNU GPL',
236 license='GNU GPL',
208 scripts=scripts,
237 scripts=scripts,
209 packages=packages,
238 packages=packages,
210 ext_modules=ext_modules,
239 ext_modules=ext_modules,
211 data_files=datafiles,
240 data_files=datafiles,
212 cmdclass=cmdclass,
241 cmdclass=cmdclass,
213 options=dict(py2exe=dict(packages=['hgext', 'email']),
242 options=dict(py2exe=dict(packages=['hgext', 'email']),
214 bdist_mpkg=dict(zipdist=True,
243 bdist_mpkg=dict(zipdist=True,
215 license='COPYING',
244 license='COPYING',
216 readme='contrib/macosx/Readme.html',
245 readme='contrib/macosx/Readme.html',
217 welcome='contrib/macosx/Welcome.html')),
246 welcome='contrib/macosx/Welcome.html')),
218 **extra)
247 **extra)
General Comments 0
You need to be logged in to leave comments. Login now