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