##// END OF EJS Templates
setup.py: move from dict() construction to {} literals...
Augie Fackler -
r20687:7d4d0429 default
parent child Browse files
Show More
@@ -1,562 +1,564 b''
1 #
1 #
2 # This is the mercurial setup script.
2 # This is the mercurial setup script.
3 #
3 #
4 # 'python setup.py install', or
4 # 'python setup.py install', or
5 # 'python setup.py --help' for more options
5 # 'python setup.py --help' for more options
6
6
7 import sys, platform
7 import sys, platform
8 if getattr(sys, 'version_info', (0, 0, 0)) < (2, 4, 0, 'final'):
8 if getattr(sys, 'version_info', (0, 0, 0)) < (2, 4, 0, 'final'):
9 raise SystemExit("Mercurial requires Python 2.4 or later.")
9 raise SystemExit("Mercurial requires Python 2.4 or later.")
10
10
11 if sys.version_info[0] >= 3:
11 if sys.version_info[0] >= 3:
12 def b(s):
12 def b(s):
13 '''A helper function to emulate 2.6+ bytes literals using string
13 '''A helper function to emulate 2.6+ bytes literals using string
14 literals.'''
14 literals.'''
15 return s.encode('latin1')
15 return s.encode('latin1')
16 else:
16 else:
17 def b(s):
17 def b(s):
18 '''A helper function to emulate 2.6+ bytes literals using string
18 '''A helper function to emulate 2.6+ bytes literals using string
19 literals.'''
19 literals.'''
20 return s
20 return s
21
21
22 # Solaris Python packaging brain damage
22 # Solaris Python packaging brain damage
23 try:
23 try:
24 import hashlib
24 import hashlib
25 sha = hashlib.sha1()
25 sha = hashlib.sha1()
26 except ImportError:
26 except ImportError:
27 try:
27 try:
28 import sha
28 import sha
29 except ImportError:
29 except ImportError:
30 raise SystemExit(
30 raise SystemExit(
31 "Couldn't import standard hashlib (incomplete Python install).")
31 "Couldn't import standard hashlib (incomplete Python install).")
32
32
33 try:
33 try:
34 import zlib
34 import zlib
35 except ImportError:
35 except ImportError:
36 raise SystemExit(
36 raise SystemExit(
37 "Couldn't import standard zlib (incomplete Python install).")
37 "Couldn't import standard zlib (incomplete Python install).")
38
38
39 # The base IronPython distribution (as of 2.7.1) doesn't support bz2
39 # The base IronPython distribution (as of 2.7.1) doesn't support bz2
40 isironpython = False
40 isironpython = False
41 try:
41 try:
42 isironpython = (platform.python_implementation()
42 isironpython = (platform.python_implementation()
43 .lower().find("ironpython") != -1)
43 .lower().find("ironpython") != -1)
44 except AttributeError:
44 except AttributeError:
45 pass
45 pass
46
46
47 if isironpython:
47 if isironpython:
48 sys.stderr.write("warning: IronPython detected (no bz2 support)\n")
48 sys.stderr.write("warning: IronPython detected (no bz2 support)\n")
49 else:
49 else:
50 try:
50 try:
51 import bz2
51 import bz2
52 except ImportError:
52 except ImportError:
53 raise SystemExit(
53 raise SystemExit(
54 "Couldn't import standard bz2 (incomplete Python install).")
54 "Couldn't import standard bz2 (incomplete Python install).")
55
55
56 import os, subprocess, time
56 import os, subprocess, time
57 import shutil
57 import shutil
58 import tempfile
58 import tempfile
59 from distutils import log
59 from distutils import log
60 from distutils.core import setup, Command, Extension
60 from distutils.core import setup, Command, Extension
61 from distutils.dist import Distribution
61 from distutils.dist import Distribution
62 from distutils.command.build import build
62 from distutils.command.build import build
63 from distutils.command.build_ext import build_ext
63 from distutils.command.build_ext import build_ext
64 from distutils.command.build_py import build_py
64 from distutils.command.build_py import build_py
65 from distutils.command.install_scripts import install_scripts
65 from distutils.command.install_scripts import install_scripts
66 from distutils.spawn import spawn, find_executable
66 from distutils.spawn import spawn, find_executable
67 from distutils import cygwinccompiler
67 from distutils import cygwinccompiler
68 from distutils.errors import CCompilerError, DistutilsExecError
68 from distutils.errors import CCompilerError, DistutilsExecError
69 from distutils.sysconfig import get_python_inc
69 from distutils.sysconfig import get_python_inc
70 from distutils.version import StrictVersion
70 from distutils.version import StrictVersion
71
71
72 convert2to3 = '--c2to3' in sys.argv
72 convert2to3 = '--c2to3' in sys.argv
73 if convert2to3:
73 if convert2to3:
74 try:
74 try:
75 from distutils.command.build_py import build_py_2to3 as build_py
75 from distutils.command.build_py import build_py_2to3 as build_py
76 from lib2to3.refactor import get_fixers_from_package as getfixers
76 from lib2to3.refactor import get_fixers_from_package as getfixers
77 except ImportError:
77 except ImportError:
78 if sys.version_info[0] < 3:
78 if sys.version_info[0] < 3:
79 raise SystemExit("--c2to3 is only compatible with python3.")
79 raise SystemExit("--c2to3 is only compatible with python3.")
80 raise
80 raise
81 sys.path.append('contrib')
81 sys.path.append('contrib')
82 elif sys.version_info[0] >= 3:
82 elif sys.version_info[0] >= 3:
83 raise SystemExit("setup.py with python3 needs --c2to3 (experimental)")
83 raise SystemExit("setup.py with python3 needs --c2to3 (experimental)")
84
84
85 scripts = ['hg']
85 scripts = ['hg']
86 if os.name == 'nt':
86 if os.name == 'nt':
87 scripts.append('contrib/win32/hg.bat')
87 scripts.append('contrib/win32/hg.bat')
88
88
89 # simplified version of distutils.ccompiler.CCompiler.has_function
89 # simplified version of distutils.ccompiler.CCompiler.has_function
90 # that actually removes its temporary files.
90 # that actually removes its temporary files.
91 def hasfunction(cc, funcname):
91 def hasfunction(cc, funcname):
92 tmpdir = tempfile.mkdtemp(prefix='hg-install-')
92 tmpdir = tempfile.mkdtemp(prefix='hg-install-')
93 devnull = oldstderr = None
93 devnull = oldstderr = None
94 try:
94 try:
95 try:
95 try:
96 fname = os.path.join(tmpdir, 'funcname.c')
96 fname = os.path.join(tmpdir, 'funcname.c')
97 f = open(fname, 'w')
97 f = open(fname, 'w')
98 f.write('int main(void) {\n')
98 f.write('int main(void) {\n')
99 f.write(' %s();\n' % funcname)
99 f.write(' %s();\n' % funcname)
100 f.write('}\n')
100 f.write('}\n')
101 f.close()
101 f.close()
102 # Redirect stderr to /dev/null to hide any error messages
102 # Redirect stderr to /dev/null to hide any error messages
103 # from the compiler.
103 # from the compiler.
104 # This will have to be changed if we ever have to check
104 # This will have to be changed if we ever have to check
105 # for a function on Windows.
105 # for a function on Windows.
106 devnull = open('/dev/null', 'w')
106 devnull = open('/dev/null', 'w')
107 oldstderr = os.dup(sys.stderr.fileno())
107 oldstderr = os.dup(sys.stderr.fileno())
108 os.dup2(devnull.fileno(), sys.stderr.fileno())
108 os.dup2(devnull.fileno(), sys.stderr.fileno())
109 objects = cc.compile([fname], output_dir=tmpdir)
109 objects = cc.compile([fname], output_dir=tmpdir)
110 cc.link_executable(objects, os.path.join(tmpdir, "a.out"))
110 cc.link_executable(objects, os.path.join(tmpdir, "a.out"))
111 except Exception:
111 except Exception:
112 return False
112 return False
113 return True
113 return True
114 finally:
114 finally:
115 if oldstderr is not None:
115 if oldstderr is not None:
116 os.dup2(oldstderr, sys.stderr.fileno())
116 os.dup2(oldstderr, sys.stderr.fileno())
117 if devnull is not None:
117 if devnull is not None:
118 devnull.close()
118 devnull.close()
119 shutil.rmtree(tmpdir)
119 shutil.rmtree(tmpdir)
120
120
121 # py2exe needs to be installed to work
121 # py2exe needs to be installed to work
122 try:
122 try:
123 import py2exe
123 import py2exe
124 py2exeloaded = True
124 py2exeloaded = True
125 # import py2exe's patched Distribution class
125 # import py2exe's patched Distribution class
126 from distutils.core import Distribution
126 from distutils.core import Distribution
127 except ImportError:
127 except ImportError:
128 py2exeloaded = False
128 py2exeloaded = False
129
129
130 def runcmd(cmd, env):
130 def runcmd(cmd, env):
131 if sys.platform == 'plan9':
131 if sys.platform == 'plan9':
132 # subprocess kludge to work around issues in half-baked Python
132 # subprocess kludge to work around issues in half-baked Python
133 # ports, notably bichued/python:
133 # ports, notably bichued/python:
134 _, out, err = os.popen3(cmd)
134 _, out, err = os.popen3(cmd)
135 return str(out), str(err)
135 return str(out), str(err)
136 else:
136 else:
137 p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
137 p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
138 stderr=subprocess.PIPE, env=env)
138 stderr=subprocess.PIPE, env=env)
139 out, err = p.communicate()
139 out, err = p.communicate()
140 return out, err
140 return out, err
141
141
142 def runhg(cmd, env):
142 def runhg(cmd, env):
143 out, err = runcmd(cmd, env)
143 out, err = runcmd(cmd, env)
144 # If root is executing setup.py, but the repository is owned by
144 # If root is executing setup.py, but the repository is owned by
145 # another user (as in "sudo python setup.py install") we will get
145 # another user (as in "sudo python setup.py install") we will get
146 # trust warnings since the .hg/hgrc file is untrusted. That is
146 # trust warnings since the .hg/hgrc file is untrusted. That is
147 # fine, we don't want to load it anyway. Python may warn about
147 # fine, we don't want to load it anyway. Python may warn about
148 # a missing __init__.py in mercurial/locale, we also ignore that.
148 # a missing __init__.py in mercurial/locale, we also ignore that.
149 err = [e for e in err.splitlines()
149 err = [e for e in err.splitlines()
150 if not e.startswith(b('not trusting file')) \
150 if not e.startswith(b('not trusting file')) \
151 and not e.startswith(b('warning: Not importing')) \
151 and not e.startswith(b('warning: Not importing')) \
152 and not e.startswith(b('obsolete feature not enabled'))]
152 and not e.startswith(b('obsolete feature not enabled'))]
153 if err:
153 if err:
154 print >> sys.stderr, "stderr from '%s':" % (' '.join(cmd))
154 print >> sys.stderr, "stderr from '%s':" % (' '.join(cmd))
155 print >> sys.stderr, '\n'.join([' ' + e for e in err])
155 print >> sys.stderr, '\n'.join([' ' + e for e in err])
156 return ''
156 return ''
157 return out
157 return out
158
158
159 version = ''
159 version = ''
160
160
161 # Execute hg out of this directory with a custom environment which
161 # Execute hg out of this directory with a custom environment which
162 # includes the pure Python modules in mercurial/pure. We also take
162 # includes the pure Python modules in mercurial/pure. We also take
163 # care to not use any hgrc files and do no localization.
163 # care to not use any hgrc files and do no localization.
164 pypath = ['mercurial', os.path.join('mercurial', 'pure')]
164 pypath = ['mercurial', os.path.join('mercurial', 'pure')]
165 env = {'PYTHONPATH': os.pathsep.join(pypath),
165 env = {'PYTHONPATH': os.pathsep.join(pypath),
166 'HGRCPATH': '',
166 'HGRCPATH': '',
167 'LANGUAGE': 'C'}
167 'LANGUAGE': 'C'}
168 if 'LD_LIBRARY_PATH' in os.environ:
168 if 'LD_LIBRARY_PATH' in os.environ:
169 env['LD_LIBRARY_PATH'] = os.environ['LD_LIBRARY_PATH']
169 env['LD_LIBRARY_PATH'] = os.environ['LD_LIBRARY_PATH']
170 if 'SystemRoot' in os.environ:
170 if 'SystemRoot' in os.environ:
171 # Copy SystemRoot into the custom environment for Python 2.6
171 # Copy SystemRoot into the custom environment for Python 2.6
172 # under Windows. Otherwise, the subprocess will fail with
172 # under Windows. Otherwise, the subprocess will fail with
173 # error 0xc0150004. See: http://bugs.python.org/issue3440
173 # error 0xc0150004. See: http://bugs.python.org/issue3440
174 env['SystemRoot'] = os.environ['SystemRoot']
174 env['SystemRoot'] = os.environ['SystemRoot']
175
175
176 if os.path.isdir('.hg'):
176 if os.path.isdir('.hg'):
177 cmd = [sys.executable, 'hg', 'log', '-r', '.', '--template', '{tags}\n']
177 cmd = [sys.executable, 'hg', 'log', '-r', '.', '--template', '{tags}\n']
178 numerictags = [t for t in runhg(cmd, env).split() if t[0].isdigit()]
178 numerictags = [t for t in runhg(cmd, env).split() if t[0].isdigit()]
179 hgid = runhg([sys.executable, 'hg', 'id', '-i'], env).strip()
179 hgid = runhg([sys.executable, 'hg', 'id', '-i'], env).strip()
180 if numerictags: # tag(s) found
180 if numerictags: # tag(s) found
181 version = numerictags[-1]
181 version = numerictags[-1]
182 if hgid.endswith('+'): # propagate the dirty status to the tag
182 if hgid.endswith('+'): # propagate the dirty status to the tag
183 version += '+'
183 version += '+'
184 else: # no tag found
184 else: # no tag found
185 cmd = [sys.executable, 'hg', 'parents', '--template',
185 cmd = [sys.executable, 'hg', 'parents', '--template',
186 '{latesttag}+{latesttagdistance}-']
186 '{latesttag}+{latesttagdistance}-']
187 version = runhg(cmd, env) + hgid
187 version = runhg(cmd, env) + hgid
188 if version.endswith('+'):
188 if version.endswith('+'):
189 version += time.strftime('%Y%m%d')
189 version += time.strftime('%Y%m%d')
190 elif os.path.exists('.hg_archival.txt'):
190 elif os.path.exists('.hg_archival.txt'):
191 kw = dict([[t.strip() for t in l.split(':', 1)]
191 kw = dict([[t.strip() for t in l.split(':', 1)]
192 for l in open('.hg_archival.txt')])
192 for l in open('.hg_archival.txt')])
193 if 'tag' in kw:
193 if 'tag' in kw:
194 version = kw['tag']
194 version = kw['tag']
195 elif 'latesttag' in kw:
195 elif 'latesttag' in kw:
196 version = '%(latesttag)s+%(latesttagdistance)s-%(node).12s' % kw
196 version = '%(latesttag)s+%(latesttagdistance)s-%(node).12s' % kw
197 else:
197 else:
198 version = kw.get('node', '')[:12]
198 version = kw.get('node', '')[:12]
199
199
200 if version:
200 if version:
201 f = open("mercurial/__version__.py", "w")
201 f = open("mercurial/__version__.py", "w")
202 f.write('# this file is autogenerated by setup.py\n')
202 f.write('# this file is autogenerated by setup.py\n')
203 f.write('version = "%s"\n' % version)
203 f.write('version = "%s"\n' % version)
204 f.close()
204 f.close()
205
205
206
206
207 try:
207 try:
208 from mercurial import __version__
208 from mercurial import __version__
209 version = __version__.version
209 version = __version__.version
210 except ImportError:
210 except ImportError:
211 version = 'unknown'
211 version = 'unknown'
212
212
213 class hgbuild(build):
213 class hgbuild(build):
214 # Insert hgbuildmo first so that files in mercurial/locale/ are found
214 # Insert hgbuildmo first so that files in mercurial/locale/ are found
215 # when build_py is run next.
215 # when build_py is run next.
216 sub_commands = [('build_mo', None),
216 sub_commands = [('build_mo', None),
217
217
218 # We also need build_ext before build_py. Otherwise, when 2to3 is
218 # We also need build_ext before build_py. Otherwise, when 2to3 is
219 # called (in build_py), it will not find osutil & friends,
219 # called (in build_py), it will not find osutil & friends,
220 # thinking that those modules are global and, consequently, making
220 # thinking that those modules are global and, consequently, making
221 # a mess, now that all module imports are global.
221 # a mess, now that all module imports are global.
222
222
223 ('build_ext', build.has_ext_modules),
223 ('build_ext', build.has_ext_modules),
224 ] + build.sub_commands
224 ] + build.sub_commands
225
225
226 class hgbuildmo(build):
226 class hgbuildmo(build):
227
227
228 description = "build translations (.mo files)"
228 description = "build translations (.mo files)"
229
229
230 def run(self):
230 def run(self):
231 if not find_executable('msgfmt'):
231 if not find_executable('msgfmt'):
232 self.warn("could not find msgfmt executable, no translations "
232 self.warn("could not find msgfmt executable, no translations "
233 "will be built")
233 "will be built")
234 return
234 return
235
235
236 podir = 'i18n'
236 podir = 'i18n'
237 if not os.path.isdir(podir):
237 if not os.path.isdir(podir):
238 self.warn("could not find %s/ directory" % podir)
238 self.warn("could not find %s/ directory" % podir)
239 return
239 return
240
240
241 join = os.path.join
241 join = os.path.join
242 for po in os.listdir(podir):
242 for po in os.listdir(podir):
243 if not po.endswith('.po'):
243 if not po.endswith('.po'):
244 continue
244 continue
245 pofile = join(podir, po)
245 pofile = join(podir, po)
246 modir = join('locale', po[:-3], 'LC_MESSAGES')
246 modir = join('locale', po[:-3], 'LC_MESSAGES')
247 mofile = join(modir, 'hg.mo')
247 mofile = join(modir, 'hg.mo')
248 mobuildfile = join('mercurial', mofile)
248 mobuildfile = join('mercurial', mofile)
249 cmd = ['msgfmt', '-v', '-o', mobuildfile, pofile]
249 cmd = ['msgfmt', '-v', '-o', mobuildfile, pofile]
250 if sys.platform != 'sunos5':
250 if sys.platform != 'sunos5':
251 # msgfmt on Solaris does not know about -c
251 # msgfmt on Solaris does not know about -c
252 cmd.append('-c')
252 cmd.append('-c')
253 self.mkpath(join('mercurial', modir))
253 self.mkpath(join('mercurial', modir))
254 self.make_file([pofile], mobuildfile, spawn, (cmd,))
254 self.make_file([pofile], mobuildfile, spawn, (cmd,))
255
255
256
256
257 class hgdist(Distribution):
257 class hgdist(Distribution):
258 pure = 0
258 pure = 0
259
259
260 global_options = Distribution.global_options + \
260 global_options = Distribution.global_options + \
261 [('pure', None, "use pure (slow) Python "
261 [('pure', None, "use pure (slow) Python "
262 "code instead of C extensions"),
262 "code instead of C extensions"),
263 ('c2to3', None, "(experimental!) convert "
263 ('c2to3', None, "(experimental!) convert "
264 "code with 2to3"),
264 "code with 2to3"),
265 ]
265 ]
266
266
267 def has_ext_modules(self):
267 def has_ext_modules(self):
268 # self.ext_modules is emptied in hgbuildpy.finalize_options which is
268 # self.ext_modules is emptied in hgbuildpy.finalize_options which is
269 # too late for some cases
269 # too late for some cases
270 return not self.pure and Distribution.has_ext_modules(self)
270 return not self.pure and Distribution.has_ext_modules(self)
271
271
272 class hgbuildext(build_ext):
272 class hgbuildext(build_ext):
273
273
274 def build_extension(self, ext):
274 def build_extension(self, ext):
275 try:
275 try:
276 build_ext.build_extension(self, ext)
276 build_ext.build_extension(self, ext)
277 except CCompilerError:
277 except CCompilerError:
278 if not getattr(ext, 'optional', False):
278 if not getattr(ext, 'optional', False):
279 raise
279 raise
280 log.warn("Failed to build optional extension '%s' (skipping)",
280 log.warn("Failed to build optional extension '%s' (skipping)",
281 ext.name)
281 ext.name)
282
282
283 class hgbuildpy(build_py):
283 class hgbuildpy(build_py):
284 if convert2to3:
284 if convert2to3:
285 fixer_names = sorted(set(getfixers("lib2to3.fixes") +
285 fixer_names = sorted(set(getfixers("lib2to3.fixes") +
286 getfixers("hgfixes")))
286 getfixers("hgfixes")))
287
287
288 def finalize_options(self):
288 def finalize_options(self):
289 build_py.finalize_options(self)
289 build_py.finalize_options(self)
290
290
291 if self.distribution.pure:
291 if self.distribution.pure:
292 if self.py_modules is None:
292 if self.py_modules is None:
293 self.py_modules = []
293 self.py_modules = []
294 for ext in self.distribution.ext_modules:
294 for ext in self.distribution.ext_modules:
295 if ext.name.startswith("mercurial."):
295 if ext.name.startswith("mercurial."):
296 self.py_modules.append("mercurial.pure.%s" % ext.name[10:])
296 self.py_modules.append("mercurial.pure.%s" % ext.name[10:])
297 self.distribution.ext_modules = []
297 self.distribution.ext_modules = []
298 else:
298 else:
299 h = os.path.join(get_python_inc(), 'Python.h')
299 h = os.path.join(get_python_inc(), 'Python.h')
300 if not os.path.exists(h):
300 if not os.path.exists(h):
301 raise SystemExit('Python headers are required to build '
301 raise SystemExit('Python headers are required to build '
302 'Mercurial but weren\'t found in %s' % h)
302 'Mercurial but weren\'t found in %s' % h)
303
303
304 def find_modules(self):
304 def find_modules(self):
305 modules = build_py.find_modules(self)
305 modules = build_py.find_modules(self)
306 for module in modules:
306 for module in modules:
307 if module[0] == "mercurial.pure":
307 if module[0] == "mercurial.pure":
308 if module[1] != "__init__":
308 if module[1] != "__init__":
309 yield ("mercurial", module[1], module[2])
309 yield ("mercurial", module[1], module[2])
310 else:
310 else:
311 yield module
311 yield module
312
312
313 class buildhgextindex(Command):
313 class buildhgextindex(Command):
314 description = 'generate prebuilt index of hgext (for frozen package)'
314 description = 'generate prebuilt index of hgext (for frozen package)'
315 user_options = []
315 user_options = []
316 _indexfilename = 'hgext/__index__.py'
316 _indexfilename = 'hgext/__index__.py'
317
317
318 def initialize_options(self):
318 def initialize_options(self):
319 pass
319 pass
320
320
321 def finalize_options(self):
321 def finalize_options(self):
322 pass
322 pass
323
323
324 def run(self):
324 def run(self):
325 if os.path.exists(self._indexfilename):
325 if os.path.exists(self._indexfilename):
326 os.unlink(self._indexfilename)
326 os.unlink(self._indexfilename)
327
327
328 # here no extension enabled, disabled() lists up everything
328 # here no extension enabled, disabled() lists up everything
329 code = ('import pprint; from mercurial import extensions; '
329 code = ('import pprint; from mercurial import extensions; '
330 'pprint.pprint(extensions.disabled())')
330 'pprint.pprint(extensions.disabled())')
331 out, err = runcmd([sys.executable, '-c', code], env)
331 out, err = runcmd([sys.executable, '-c', code], env)
332 if err:
332 if err:
333 raise DistutilsExecError(err)
333 raise DistutilsExecError(err)
334
334
335 f = open(self._indexfilename, 'w')
335 f = open(self._indexfilename, 'w')
336 f.write('# this file is autogenerated by setup.py\n')
336 f.write('# this file is autogenerated by setup.py\n')
337 f.write('docs = ')
337 f.write('docs = ')
338 f.write(out)
338 f.write(out)
339 f.close()
339 f.close()
340
340
341 class buildhgexe(build_ext):
341 class buildhgexe(build_ext):
342 description = 'compile hg.exe from mercurial/exewrapper.c'
342 description = 'compile hg.exe from mercurial/exewrapper.c'
343
343
344 def build_extensions(self):
344 def build_extensions(self):
345 if os.name != 'nt':
345 if os.name != 'nt':
346 return
346 return
347 if isinstance(self.compiler, HackedMingw32CCompiler):
347 if isinstance(self.compiler, HackedMingw32CCompiler):
348 self.compiler.compiler_so = self.compiler.compiler # no -mdll
348 self.compiler.compiler_so = self.compiler.compiler # no -mdll
349 self.compiler.dll_libraries = [] # no -lmsrvc90
349 self.compiler.dll_libraries = [] # no -lmsrvc90
350 hv = sys.hexversion
350 hv = sys.hexversion
351 pythonlib = 'python%d%d' % (hv >> 24, (hv >> 16) & 0xff)
351 pythonlib = 'python%d%d' % (hv >> 24, (hv >> 16) & 0xff)
352 f = open('mercurial/hgpythonlib.h', 'wb')
352 f = open('mercurial/hgpythonlib.h', 'wb')
353 f.write('/* this file is autogenerated by setup.py */\n')
353 f.write('/* this file is autogenerated by setup.py */\n')
354 f.write('#define HGPYTHONLIB "%s"\n' % pythonlib)
354 f.write('#define HGPYTHONLIB "%s"\n' % pythonlib)
355 f.close()
355 f.close()
356 objects = self.compiler.compile(['mercurial/exewrapper.c'],
356 objects = self.compiler.compile(['mercurial/exewrapper.c'],
357 output_dir=self.build_temp)
357 output_dir=self.build_temp)
358 dir = os.path.dirname(self.get_ext_fullpath('dummy'))
358 dir = os.path.dirname(self.get_ext_fullpath('dummy'))
359 target = os.path.join(dir, 'hg')
359 target = os.path.join(dir, 'hg')
360 self.compiler.link_executable(objects, target,
360 self.compiler.link_executable(objects, target,
361 libraries=[],
361 libraries=[],
362 output_dir=self.build_temp)
362 output_dir=self.build_temp)
363
363
364 class hginstallscripts(install_scripts):
364 class hginstallscripts(install_scripts):
365 '''
365 '''
366 This is a specialization of install_scripts that replaces the @LIBDIR@ with
366 This is a specialization of install_scripts that replaces the @LIBDIR@ with
367 the configured directory for modules. If possible, the path is made relative
367 the configured directory for modules. If possible, the path is made relative
368 to the directory for scripts.
368 to the directory for scripts.
369 '''
369 '''
370
370
371 def initialize_options(self):
371 def initialize_options(self):
372 install_scripts.initialize_options(self)
372 install_scripts.initialize_options(self)
373
373
374 self.install_lib = None
374 self.install_lib = None
375
375
376 def finalize_options(self):
376 def finalize_options(self):
377 install_scripts.finalize_options(self)
377 install_scripts.finalize_options(self)
378 self.set_undefined_options('install',
378 self.set_undefined_options('install',
379 ('install_lib', 'install_lib'))
379 ('install_lib', 'install_lib'))
380
380
381 def run(self):
381 def run(self):
382 install_scripts.run(self)
382 install_scripts.run(self)
383
383
384 if (os.path.splitdrive(self.install_dir)[0] !=
384 if (os.path.splitdrive(self.install_dir)[0] !=
385 os.path.splitdrive(self.install_lib)[0]):
385 os.path.splitdrive(self.install_lib)[0]):
386 # can't make relative paths from one drive to another, so use an
386 # can't make relative paths from one drive to another, so use an
387 # absolute path instead
387 # absolute path instead
388 libdir = self.install_lib
388 libdir = self.install_lib
389 else:
389 else:
390 common = os.path.commonprefix((self.install_dir, self.install_lib))
390 common = os.path.commonprefix((self.install_dir, self.install_lib))
391 rest = self.install_dir[len(common):]
391 rest = self.install_dir[len(common):]
392 uplevel = len([n for n in os.path.split(rest) if n])
392 uplevel = len([n for n in os.path.split(rest) if n])
393
393
394 libdir = uplevel * ('..' + os.sep) + self.install_lib[len(common):]
394 libdir = uplevel * ('..' + os.sep) + self.install_lib[len(common):]
395
395
396 for outfile in self.outfiles:
396 for outfile in self.outfiles:
397 fp = open(outfile, 'rb')
397 fp = open(outfile, 'rb')
398 data = fp.read()
398 data = fp.read()
399 fp.close()
399 fp.close()
400
400
401 # skip binary files
401 # skip binary files
402 if b('\0') in data:
402 if b('\0') in data:
403 continue
403 continue
404
404
405 data = data.replace('@LIBDIR@', libdir.encode('string_escape'))
405 data = data.replace('@LIBDIR@', libdir.encode('string_escape'))
406 fp = open(outfile, 'wb')
406 fp = open(outfile, 'wb')
407 fp.write(data)
407 fp.write(data)
408 fp.close()
408 fp.close()
409
409
410 cmdclass = {'build': hgbuild,
410 cmdclass = {'build': hgbuild,
411 'build_mo': hgbuildmo,
411 'build_mo': hgbuildmo,
412 'build_ext': hgbuildext,
412 'build_ext': hgbuildext,
413 'build_py': hgbuildpy,
413 'build_py': hgbuildpy,
414 'build_hgextindex': buildhgextindex,
414 'build_hgextindex': buildhgextindex,
415 'install_scripts': hginstallscripts,
415 'install_scripts': hginstallscripts,
416 'build_hgexe': buildhgexe,
416 'build_hgexe': buildhgexe,
417 }
417 }
418
418
419 packages = ['mercurial', 'mercurial.hgweb', 'mercurial.httpclient',
419 packages = ['mercurial', 'mercurial.hgweb', 'mercurial.httpclient',
420 'hgext', 'hgext.convert', 'hgext.highlight', 'hgext.zeroconf',
420 'hgext', 'hgext.convert', 'hgext.highlight', 'hgext.zeroconf',
421 'hgext.largefiles']
421 'hgext.largefiles']
422
422
423 pymodules = []
423 pymodules = []
424
424
425 common_depends = ['mercurial/util.h']
425 common_depends = ['mercurial/util.h']
426
426
427 extmodules = [
427 extmodules = [
428 Extension('mercurial.base85', ['mercurial/base85.c'],
428 Extension('mercurial.base85', ['mercurial/base85.c'],
429 depends=common_depends),
429 depends=common_depends),
430 Extension('mercurial.bdiff', ['mercurial/bdiff.c'],
430 Extension('mercurial.bdiff', ['mercurial/bdiff.c'],
431 depends=common_depends),
431 depends=common_depends),
432 Extension('mercurial.diffhelpers', ['mercurial/diffhelpers.c'],
432 Extension('mercurial.diffhelpers', ['mercurial/diffhelpers.c'],
433 depends=common_depends),
433 depends=common_depends),
434 Extension('mercurial.mpatch', ['mercurial/mpatch.c'],
434 Extension('mercurial.mpatch', ['mercurial/mpatch.c'],
435 depends=common_depends),
435 depends=common_depends),
436 Extension('mercurial.parsers', ['mercurial/dirs.c',
436 Extension('mercurial.parsers', ['mercurial/dirs.c',
437 'mercurial/parsers.c',
437 'mercurial/parsers.c',
438 'mercurial/pathencode.c'],
438 'mercurial/pathencode.c'],
439 depends=common_depends),
439 depends=common_depends),
440 ]
440 ]
441
441
442 osutil_ldflags = []
442 osutil_ldflags = []
443
443
444 if sys.platform == 'darwin':
444 if sys.platform == 'darwin':
445 osutil_ldflags += ['-framework', 'ApplicationServices']
445 osutil_ldflags += ['-framework', 'ApplicationServices']
446
446
447 # disable osutil.c under windows + python 2.4 (issue1364)
447 # disable osutil.c under windows + python 2.4 (issue1364)
448 if sys.platform == 'win32' and sys.version_info < (2, 5, 0, 'final'):
448 if sys.platform == 'win32' and sys.version_info < (2, 5, 0, 'final'):
449 pymodules.append('mercurial.pure.osutil')
449 pymodules.append('mercurial.pure.osutil')
450 else:
450 else:
451 extmodules.append(Extension('mercurial.osutil', ['mercurial/osutil.c'],
451 extmodules.append(Extension('mercurial.osutil', ['mercurial/osutil.c'],
452 extra_link_args=osutil_ldflags,
452 extra_link_args=osutil_ldflags,
453 depends=common_depends))
453 depends=common_depends))
454
454
455 # the -mno-cygwin option has been deprecated for years
455 # the -mno-cygwin option has been deprecated for years
456 Mingw32CCompiler = cygwinccompiler.Mingw32CCompiler
456 Mingw32CCompiler = cygwinccompiler.Mingw32CCompiler
457
457
458 class HackedMingw32CCompiler(cygwinccompiler.Mingw32CCompiler):
458 class HackedMingw32CCompiler(cygwinccompiler.Mingw32CCompiler):
459 def __init__(self, *args, **kwargs):
459 def __init__(self, *args, **kwargs):
460 Mingw32CCompiler.__init__(self, *args, **kwargs)
460 Mingw32CCompiler.__init__(self, *args, **kwargs)
461 for i in 'compiler compiler_so linker_exe linker_so'.split():
461 for i in 'compiler compiler_so linker_exe linker_so'.split():
462 try:
462 try:
463 getattr(self, i).remove('-mno-cygwin')
463 getattr(self, i).remove('-mno-cygwin')
464 except ValueError:
464 except ValueError:
465 pass
465 pass
466
466
467 cygwinccompiler.Mingw32CCompiler = HackedMingw32CCompiler
467 cygwinccompiler.Mingw32CCompiler = HackedMingw32CCompiler
468
468
469 packagedata = {'mercurial': ['locale/*/LC_MESSAGES/hg.mo',
469 packagedata = {'mercurial': ['locale/*/LC_MESSAGES/hg.mo',
470 'help/*.txt']}
470 'help/*.txt']}
471
471
472 def ordinarypath(p):
472 def ordinarypath(p):
473 return p and p[0] != '.' and p[-1] != '~'
473 return p and p[0] != '.' and p[-1] != '~'
474
474
475 for root in ('templates',):
475 for root in ('templates',):
476 for curdir, dirs, files in os.walk(os.path.join('mercurial', root)):
476 for curdir, dirs, files in os.walk(os.path.join('mercurial', root)):
477 curdir = curdir.split(os.sep, 1)[1]
477 curdir = curdir.split(os.sep, 1)[1]
478 dirs[:] = filter(ordinarypath, dirs)
478 dirs[:] = filter(ordinarypath, dirs)
479 for f in filter(ordinarypath, files):
479 for f in filter(ordinarypath, files):
480 f = os.path.join(curdir, f)
480 f = os.path.join(curdir, f)
481 packagedata['mercurial'].append(f)
481 packagedata['mercurial'].append(f)
482
482
483 datafiles = []
483 datafiles = []
484 setupversion = version
484 setupversion = version
485 extra = {}
485 extra = {}
486
486
487 if py2exeloaded:
487 if py2exeloaded:
488 extra['console'] = [
488 extra['console'] = [
489 {'script':'hg',
489 {'script':'hg',
490 'copyright':'Copyright (C) 2005-2010 Matt Mackall and others',
490 'copyright':'Copyright (C) 2005-2010 Matt Mackall and others',
491 'product_version':version}]
491 'product_version':version}]
492 # sub command of 'build' because 'py2exe' does not handle sub_commands
492 # sub command of 'build' because 'py2exe' does not handle sub_commands
493 build.sub_commands.insert(0, ('build_hgextindex', None))
493 build.sub_commands.insert(0, ('build_hgextindex', None))
494
494
495 if os.name == 'nt':
495 if os.name == 'nt':
496 # Windows binary file versions for exe/dll files must have the
496 # Windows binary file versions for exe/dll files must have the
497 # form W.X.Y.Z, where W,X,Y,Z are numbers in the range 0..65535
497 # form W.X.Y.Z, where W,X,Y,Z are numbers in the range 0..65535
498 setupversion = version.split('+', 1)[0]
498 setupversion = version.split('+', 1)[0]
499
499
500 if sys.platform == 'darwin' and os.path.exists('/usr/bin/xcodebuild'):
500 if sys.platform == 'darwin' and os.path.exists('/usr/bin/xcodebuild'):
501 # XCode 4.0 dropped support for ppc architecture, which is hardcoded in
501 # XCode 4.0 dropped support for ppc architecture, which is hardcoded in
502 # distutils.sysconfig
502 # distutils.sysconfig
503 version = runcmd(['/usr/bin/xcodebuild', '-version'], {})[0].splitlines()
503 version = runcmd(['/usr/bin/xcodebuild', '-version'], {})[0].splitlines()
504 if version:
504 if version:
505 version = version[0]
505 version = version[0]
506 xcode4 = (version.startswith('Xcode') and
506 xcode4 = (version.startswith('Xcode') and
507 StrictVersion(version.split()[1]) >= StrictVersion('4.0'))
507 StrictVersion(version.split()[1]) >= StrictVersion('4.0'))
508 else:
508 else:
509 # xcodebuild returns empty on OS X Lion with XCode 4.3 not
509 # xcodebuild returns empty on OS X Lion with XCode 4.3 not
510 # installed, but instead with only command-line tools. Assume
510 # installed, but instead with only command-line tools. Assume
511 # that only happens on >= Lion, thus no PPC support.
511 # that only happens on >= Lion, thus no PPC support.
512 xcode4 = True
512 xcode4 = True
513
513
514 if xcode4:
514 if xcode4:
515 os.environ['ARCHFLAGS'] = ''
515 os.environ['ARCHFLAGS'] = ''
516
516
517 setup(name='mercurial',
517 setup(name='mercurial',
518 version=setupversion,
518 version=setupversion,
519 author='Matt Mackall and many others',
519 author='Matt Mackall and many others',
520 author_email='mercurial@selenic.com',
520 author_email='mercurial@selenic.com',
521 url='http://mercurial.selenic.com/',
521 url='http://mercurial.selenic.com/',
522 download_url='http://mercurial.selenic.com/release/',
522 download_url='http://mercurial.selenic.com/release/',
523 description=('Fast scalable distributed SCM (revision control, version '
523 description=('Fast scalable distributed SCM (revision control, version '
524 'control) system'),
524 'control) system'),
525 long_description=('Mercurial is a distributed SCM tool written in Python.'
525 long_description=('Mercurial is a distributed SCM tool written in Python.'
526 ' It is used by a number of large projects that require'
526 ' It is used by a number of large projects that require'
527 ' fast, reliable distributed revision control, such as '
527 ' fast, reliable distributed revision control, such as '
528 'Mozilla.'),
528 'Mozilla.'),
529 license='GNU GPLv2 or any later version',
529 license='GNU GPLv2 or any later version',
530 classifiers=[
530 classifiers=[
531 'Development Status :: 6 - Mature',
531 'Development Status :: 6 - Mature',
532 'Environment :: Console',
532 'Environment :: Console',
533 'Intended Audience :: Developers',
533 'Intended Audience :: Developers',
534 'Intended Audience :: System Administrators',
534 'Intended Audience :: System Administrators',
535 'License :: OSI Approved :: GNU General Public License (GPL)',
535 'License :: OSI Approved :: GNU General Public License (GPL)',
536 'Natural Language :: Danish',
536 'Natural Language :: Danish',
537 'Natural Language :: English',
537 'Natural Language :: English',
538 'Natural Language :: German',
538 'Natural Language :: German',
539 'Natural Language :: Italian',
539 'Natural Language :: Italian',
540 'Natural Language :: Japanese',
540 'Natural Language :: Japanese',
541 'Natural Language :: Portuguese (Brazilian)',
541 'Natural Language :: Portuguese (Brazilian)',
542 'Operating System :: Microsoft :: Windows',
542 'Operating System :: Microsoft :: Windows',
543 'Operating System :: OS Independent',
543 'Operating System :: OS Independent',
544 'Operating System :: POSIX',
544 'Operating System :: POSIX',
545 'Programming Language :: C',
545 'Programming Language :: C',
546 'Programming Language :: Python',
546 'Programming Language :: Python',
547 'Topic :: Software Development :: Version Control',
547 'Topic :: Software Development :: Version Control',
548 ],
548 ],
549 scripts=scripts,
549 scripts=scripts,
550 packages=packages,
550 packages=packages,
551 py_modules=pymodules,
551 py_modules=pymodules,
552 ext_modules=extmodules,
552 ext_modules=extmodules,
553 data_files=datafiles,
553 data_files=datafiles,
554 package_data=packagedata,
554 package_data=packagedata,
555 cmdclass=cmdclass,
555 cmdclass=cmdclass,
556 distclass=hgdist,
556 distclass=hgdist,
557 options=dict(py2exe=dict(packages=['hgext', 'email']),
557 options={'py2exe': {'packages': ['hgext', 'email']},
558 bdist_mpkg=dict(zipdist=True,
558 'bdist_mpkg': {'zipdist': True,
559 license='COPYING',
559 'license': 'COPYING',
560 readme='contrib/macosx/Readme.html',
560 'readme': 'contrib/macosx/Readme.html',
561 welcome='contrib/macosx/Welcome.html')),
561 'welcome': 'contrib/macosx/Welcome.html',
562 },
563 },
562 **extra)
564 **extra)
General Comments 0
You need to be logged in to leave comments. Login now