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