##// END OF EJS Templates
fixed 0xc0150004 error building Mercurial under Python 2.6 for Windows
Garth Roxburgh-Kidd -
r8648:ca443bac default
parent child Browse files
Show More
@@ -1,266 +1,271 b''
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, 4, 0, 'final'):
9 if not hasattr(sys, 'version_info') or sys.version_info < (2, 4, 0, 'final'):
10 raise SystemExit("Mercurial requires Python 2.4 or later.")
10 raise SystemExit("Mercurial requires Python 2.4 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, subprocess, time
29 import os, subprocess, 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.dist import Distribution
34 from distutils.command.install_data import install_data
34 from distutils.command.install_data import install_data
35 from distutils.command.build import build
35 from distutils.command.build import build
36 from distutils.command.build_py import build_py
36 from distutils.command.build_py import build_py
37 from distutils.spawn import spawn, find_executable
37 from distutils.spawn import spawn, find_executable
38 from distutils.ccompiler import new_compiler
38 from distutils.ccompiler import new_compiler
39
39
40 extra = {}
40 extra = {}
41 scripts = ['hg']
41 scripts = ['hg']
42 if os.name == 'nt':
42 if os.name == 'nt':
43 scripts.append('contrib/win32/hg.bat')
43 scripts.append('contrib/win32/hg.bat')
44
44
45 # simplified version of distutils.ccompiler.CCompiler.has_function
45 # simplified version of distutils.ccompiler.CCompiler.has_function
46 # that actually removes its temporary files.
46 # that actually removes its temporary files.
47 def has_function(cc, funcname):
47 def has_function(cc, funcname):
48 tmpdir = tempfile.mkdtemp(prefix='hg-install-')
48 tmpdir = tempfile.mkdtemp(prefix='hg-install-')
49 devnull = oldstderr = None
49 devnull = oldstderr = None
50 try:
50 try:
51 try:
51 try:
52 fname = os.path.join(tmpdir, 'funcname.c')
52 fname = os.path.join(tmpdir, 'funcname.c')
53 f = open(fname, 'w')
53 f = open(fname, 'w')
54 f.write('int main(void) {\n')
54 f.write('int main(void) {\n')
55 f.write(' %s();\n' % funcname)
55 f.write(' %s();\n' % funcname)
56 f.write('}\n')
56 f.write('}\n')
57 f.close()
57 f.close()
58 # Redirect stderr to /dev/null to hide any error messages
58 # Redirect stderr to /dev/null to hide any error messages
59 # from the compiler.
59 # from the compiler.
60 # 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
61 # for a function on Windows.
61 # for a function on Windows.
62 devnull = open('/dev/null', 'w')
62 devnull = open('/dev/null', 'w')
63 oldstderr = os.dup(sys.stderr.fileno())
63 oldstderr = os.dup(sys.stderr.fileno())
64 os.dup2(devnull.fileno(), sys.stderr.fileno())
64 os.dup2(devnull.fileno(), sys.stderr.fileno())
65 objects = cc.compile([fname])
65 objects = cc.compile([fname])
66 cc.link_executable(objects, os.path.join(tmpdir, "a.out"))
66 cc.link_executable(objects, os.path.join(tmpdir, "a.out"))
67 except:
67 except:
68 return False
68 return False
69 return True
69 return True
70 finally:
70 finally:
71 if oldstderr is not None:
71 if oldstderr is not None:
72 os.dup2(oldstderr, sys.stderr.fileno())
72 os.dup2(oldstderr, sys.stderr.fileno())
73 if devnull is not None:
73 if devnull is not None:
74 devnull.close()
74 devnull.close()
75 shutil.rmtree(tmpdir)
75 shutil.rmtree(tmpdir)
76
76
77 # py2exe needs to be installed to work
77 # py2exe needs to be installed to work
78 try:
78 try:
79 import py2exe
79 import py2exe
80
80
81 # Help py2exe to find win32com.shell
81 # Help py2exe to find win32com.shell
82 try:
82 try:
83 import modulefinder
83 import modulefinder
84 import win32com
84 import win32com
85 for p in win32com.__path__[1:]: # Take the path to win32comext
85 for p in win32com.__path__[1:]: # Take the path to win32comext
86 modulefinder.AddPackagePath("win32com", p)
86 modulefinder.AddPackagePath("win32com", p)
87 pn = "win32com.shell"
87 pn = "win32com.shell"
88 __import__(pn)
88 __import__(pn)
89 m = sys.modules[pn]
89 m = sys.modules[pn]
90 for p in m.__path__[1:]:
90 for p in m.__path__[1:]:
91 modulefinder.AddPackagePath(pn, p)
91 modulefinder.AddPackagePath(pn, p)
92 except ImportError:
92 except ImportError:
93 pass
93 pass
94
94
95 extra['console'] = ['hg']
95 extra['console'] = ['hg']
96
96
97 except ImportError:
97 except ImportError:
98 pass
98 pass
99
99
100 version = None
100 version = None
101
101
102 if os.path.isdir('.hg'):
102 if os.path.isdir('.hg'):
103 # Execute hg out of this directory with a custom environment which
103 # Execute hg out of this directory with a custom environment which
104 # includes the pure Python modules in mercurial/pure. We also take
104 # includes the pure Python modules in mercurial/pure. We also take
105 # care to not use any hgrc files and do no localization.
105 # care to not use any hgrc files and do no localization.
106 pypath = ['mercurial', os.path.join('mercurial', 'pure')]
106 pypath = ['mercurial', os.path.join('mercurial', 'pure')]
107 env = {'PYTHONPATH': os.pathsep.join(pypath),
107 env = {'PYTHONPATH': os.pathsep.join(pypath),
108 'HGRCPATH': '',
108 'HGRCPATH': '',
109 'LANGUAGE': 'C'}
109 'LANGUAGE': 'C'}
110 if 'SystemRoot' in os.environ:
111 # Copy SystemRoot into the custom environment for Python 2.6
112 # under Windows. Otherwise, the subprocess will fail with
113 # error 0xc0150004. See: http://bugs.python.org/issue3440
114 env['SystemRoot'] = os.environ['SystemRoot']
110 cmd = [sys.executable, 'hg', 'id', '-i', '-t']
115 cmd = [sys.executable, 'hg', 'id', '-i', '-t']
111
116
112 p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
117 p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
113 stderr=subprocess.PIPE, env=env)
118 stderr=subprocess.PIPE, env=env)
114 out, err = p.communicate()
119 out, err = p.communicate()
115
120
116 # If root is executing setup.py, but the repository is owned by
121 # If root is executing setup.py, but the repository is owned by
117 # another user (as in "sudo python setup.py install") we will get
122 # another user (as in "sudo python setup.py install") we will get
118 # trust warnings since the .hg/hgrc file is untrusted. That is
123 # trust warnings since the .hg/hgrc file is untrusted. That is
119 # fine, we don't want to load it anyway.
124 # fine, we don't want to load it anyway.
120 err = [e for e in err.splitlines()
125 err = [e for e in err.splitlines()
121 if not e.startswith('Not trusting file')]
126 if not e.startswith('Not trusting file')]
122 if err:
127 if err:
123 sys.stderr.write('warning: could not establish Mercurial '
128 sys.stderr.write('warning: could not establish Mercurial '
124 'version:\n%s\n' % '\n'.join(err))
129 'version:\n%s\n' % '\n'.join(err))
125 else:
130 else:
126 l = out.split()
131 l = out.split()
127 while len(l) > 1 and l[-1][0].isalpha(): # remove non-numbered tags
132 while len(l) > 1 and l[-1][0].isalpha(): # remove non-numbered tags
128 l.pop()
133 l.pop()
129 if l:
134 if l:
130 version = l[-1] # latest tag or revision number
135 version = l[-1] # latest tag or revision number
131 if version.endswith('+'):
136 if version.endswith('+'):
132 version += time.strftime('%Y%m%d')
137 version += time.strftime('%Y%m%d')
133 elif os.path.exists('.hg_archival.txt'):
138 elif os.path.exists('.hg_archival.txt'):
134 hgarchival = open('.hg_archival.txt')
139 hgarchival = open('.hg_archival.txt')
135 for line in hgarchival:
140 for line in hgarchival:
136 if line.startswith('node:'):
141 if line.startswith('node:'):
137 version = line.split(':')[1].strip()[:12]
142 version = line.split(':')[1].strip()[:12]
138 break
143 break
139
144
140 if version:
145 if version:
141 f = file("mercurial/__version__.py", "w")
146 f = file("mercurial/__version__.py", "w")
142 f.write('# this file is autogenerated by setup.py\n')
147 f.write('# this file is autogenerated by setup.py\n')
143 f.write('version = "%s"\n' % version)
148 f.write('version = "%s"\n' % version)
144 f.close()
149 f.close()
145
150
146
151
147 try:
152 try:
148 from mercurial import __version__
153 from mercurial import __version__
149 version = __version__.version
154 version = __version__.version
150 except ImportError:
155 except ImportError:
151 version = 'unknown'
156 version = 'unknown'
152
157
153 class install_package_data(install_data):
158 class install_package_data(install_data):
154 def finalize_options(self):
159 def finalize_options(self):
155 self.set_undefined_options('install',
160 self.set_undefined_options('install',
156 ('install_lib', 'install_dir'))
161 ('install_lib', 'install_dir'))
157 install_data.finalize_options(self)
162 install_data.finalize_options(self)
158
163
159 class build_mo(build):
164 class build_mo(build):
160
165
161 description = "build translations (.mo files)"
166 description = "build translations (.mo files)"
162
167
163 def run(self):
168 def run(self):
164 if not find_executable('msgfmt'):
169 if not find_executable('msgfmt'):
165 self.warn("could not find msgfmt executable, no translations "
170 self.warn("could not find msgfmt executable, no translations "
166 "will be built")
171 "will be built")
167 return
172 return
168
173
169 podir = 'i18n'
174 podir = 'i18n'
170 if not os.path.isdir(podir):
175 if not os.path.isdir(podir):
171 self.warn("could not find %s/ directory" % podir)
176 self.warn("could not find %s/ directory" % podir)
172 return
177 return
173
178
174 join = os.path.join
179 join = os.path.join
175 for po in os.listdir(podir):
180 for po in os.listdir(podir):
176 if not po.endswith('.po'):
181 if not po.endswith('.po'):
177 continue
182 continue
178 pofile = join(podir, po)
183 pofile = join(podir, po)
179 modir = join('locale', po[:-3], 'LC_MESSAGES')
184 modir = join('locale', po[:-3], 'LC_MESSAGES')
180 mofile = join(modir, 'hg.mo')
185 mofile = join(modir, 'hg.mo')
181 cmd = ['msgfmt', '-v', '-o', mofile, pofile]
186 cmd = ['msgfmt', '-v', '-o', mofile, pofile]
182 if sys.platform != 'sunos5':
187 if sys.platform != 'sunos5':
183 # msgfmt on Solaris does not know about -c
188 # msgfmt on Solaris does not know about -c
184 cmd.append('-c')
189 cmd.append('-c')
185 self.mkpath(modir)
190 self.mkpath(modir)
186 self.make_file([pofile], mofile, spawn, (cmd,))
191 self.make_file([pofile], mofile, spawn, (cmd,))
187 self.distribution.data_files.append((join('mercurial', modir),
192 self.distribution.data_files.append((join('mercurial', modir),
188 [mofile]))
193 [mofile]))
189
194
190 build.sub_commands.append(('build_mo', None))
195 build.sub_commands.append(('build_mo', None))
191
196
192 Distribution.pure = 0
197 Distribution.pure = 0
193 Distribution.global_options.append(('pure', None, "use pure (slow) Python "
198 Distribution.global_options.append(('pure', None, "use pure (slow) Python "
194 "code instead of C extensions"))
199 "code instead of C extensions"))
195
200
196 class hg_build_py(build_py):
201 class hg_build_py(build_py):
197
202
198 def finalize_options(self):
203 def finalize_options(self):
199 build_py.finalize_options(self)
204 build_py.finalize_options(self)
200
205
201 if self.distribution.pure:
206 if self.distribution.pure:
202 if self.py_modules is None:
207 if self.py_modules is None:
203 self.py_modules = []
208 self.py_modules = []
204 for ext in self.distribution.ext_modules:
209 for ext in self.distribution.ext_modules:
205 if ext.name.startswith("mercurial."):
210 if ext.name.startswith("mercurial."):
206 self.py_modules.append("mercurial.pure.%s" % ext.name[10:])
211 self.py_modules.append("mercurial.pure.%s" % ext.name[10:])
207 self.distribution.ext_modules = []
212 self.distribution.ext_modules = []
208
213
209 def find_modules(self):
214 def find_modules(self):
210 modules = build_py.find_modules(self)
215 modules = build_py.find_modules(self)
211 for module in modules:
216 for module in modules:
212 if module[0] == "mercurial.pure":
217 if module[0] == "mercurial.pure":
213 if module[1] != "__init__":
218 if module[1] != "__init__":
214 yield ("mercurial", module[1], module[2])
219 yield ("mercurial", module[1], module[2])
215 else:
220 else:
216 yield module
221 yield module
217
222
218 cmdclass = {'install_data': install_package_data,
223 cmdclass = {'install_data': install_package_data,
219 'build_mo': build_mo,
224 'build_mo': build_mo,
220 'build_py': hg_build_py}
225 'build_py': hg_build_py}
221
226
222 ext_modules=[
227 ext_modules=[
223 Extension('mercurial.base85', ['mercurial/base85.c']),
228 Extension('mercurial.base85', ['mercurial/base85.c']),
224 Extension('mercurial.bdiff', ['mercurial/bdiff.c']),
229 Extension('mercurial.bdiff', ['mercurial/bdiff.c']),
225 Extension('mercurial.diffhelpers', ['mercurial/diffhelpers.c']),
230 Extension('mercurial.diffhelpers', ['mercurial/diffhelpers.c']),
226 Extension('mercurial.mpatch', ['mercurial/mpatch.c']),
231 Extension('mercurial.mpatch', ['mercurial/mpatch.c']),
227 Extension('mercurial.parsers', ['mercurial/parsers.c']),
232 Extension('mercurial.parsers', ['mercurial/parsers.c']),
228 Extension('mercurial.osutil', ['mercurial/osutil.c']),
233 Extension('mercurial.osutil', ['mercurial/osutil.c']),
229 ]
234 ]
230
235
231 packages = ['mercurial', 'mercurial.hgweb', 'hgext', 'hgext.convert',
236 packages = ['mercurial', 'mercurial.hgweb', 'hgext', 'hgext.convert',
232 'hgext.highlight', 'hgext.zeroconf', ]
237 'hgext.highlight', 'hgext.zeroconf', ]
233
238
234 if sys.platform == 'linux2' and os.uname()[2] > '2.6':
239 if sys.platform == 'linux2' and os.uname()[2] > '2.6':
235 # The inotify extension is only usable with Linux 2.6 kernels.
240 # The inotify extension is only usable with Linux 2.6 kernels.
236 # You also need a reasonably recent C library.
241 # You also need a reasonably recent C library.
237 cc = new_compiler()
242 cc = new_compiler()
238 if has_function(cc, 'inotify_add_watch'):
243 if has_function(cc, 'inotify_add_watch'):
239 ext_modules.append(Extension('hgext.inotify.linux._inotify',
244 ext_modules.append(Extension('hgext.inotify.linux._inotify',
240 ['hgext/inotify/linux/_inotify.c']))
245 ['hgext/inotify/linux/_inotify.c']))
241 packages.extend(['hgext.inotify', 'hgext.inotify.linux'])
246 packages.extend(['hgext.inotify', 'hgext.inotify.linux'])
242
247
243 datafiles = []
248 datafiles = []
244 for root in ('templates', 'i18n'):
249 for root in ('templates', 'i18n'):
245 for dir, dirs, files in os.walk(root):
250 for dir, dirs, files in os.walk(root):
246 datafiles.append((os.path.join('mercurial', dir),
251 datafiles.append((os.path.join('mercurial', dir),
247 [os.path.join(dir, file_) for file_ in files]))
252 [os.path.join(dir, file_) for file_ in files]))
248
253
249 setup(name='mercurial',
254 setup(name='mercurial',
250 version=version,
255 version=version,
251 author='Matt Mackall',
256 author='Matt Mackall',
252 author_email='mpm@selenic.com',
257 author_email='mpm@selenic.com',
253 url='http://selenic.com/mercurial',
258 url='http://selenic.com/mercurial',
254 description='Scalable distributed SCM',
259 description='Scalable distributed SCM',
255 license='GNU GPL',
260 license='GNU GPL',
256 scripts=scripts,
261 scripts=scripts,
257 packages=packages,
262 packages=packages,
258 ext_modules=ext_modules,
263 ext_modules=ext_modules,
259 data_files=datafiles,
264 data_files=datafiles,
260 cmdclass=cmdclass,
265 cmdclass=cmdclass,
261 options=dict(py2exe=dict(packages=['hgext', 'email']),
266 options=dict(py2exe=dict(packages=['hgext', 'email']),
262 bdist_mpkg=dict(zipdist=True,
267 bdist_mpkg=dict(zipdist=True,
263 license='COPYING',
268 license='COPYING',
264 readme='contrib/macosx/Readme.html',
269 readme='contrib/macosx/Readme.html',
265 welcome='contrib/macosx/Welcome.html')),
270 welcome='contrib/macosx/Welcome.html')),
266 **extra)
271 **extra)
General Comments 0
You need to be logged in to leave comments. Login now