##// END OF EJS Templates
setup: prepare for future cffi modules by adding placeholder in setup
Maciej Fijalkowski -
r29505:2dce3f96 default
parent child Browse files
Show More
@@ -1,707 +1,712
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, 6, 0, 'final'):
8 if getattr(sys, 'version_info', (0, 0, 0)) < (2, 6, 0, 'final'):
9 raise SystemExit("Mercurial requires Python 2.6 or later.")
9 raise SystemExit("Mercurial requires Python 2.6 or later.")
10
10
11 if sys.version_info[0] >= 3:
11 if sys.version_info[0] >= 3:
12 printf = eval('print')
12 printf = eval('print')
13 libdir_escape = 'unicode_escape'
13 libdir_escape = 'unicode_escape'
14 else:
14 else:
15 libdir_escape = 'string_escape'
15 libdir_escape = 'string_escape'
16 def printf(*args, **kwargs):
16 def printf(*args, **kwargs):
17 f = kwargs.get('file', sys.stdout)
17 f = kwargs.get('file', sys.stdout)
18 end = kwargs.get('end', '\n')
18 end = kwargs.get('end', '\n')
19 f.write(b' '.join(args) + end)
19 f.write(b' '.join(args) + end)
20
20
21 # Solaris Python packaging brain damage
21 # Solaris Python packaging brain damage
22 try:
22 try:
23 import hashlib
23 import hashlib
24 sha = hashlib.sha1()
24 sha = hashlib.sha1()
25 except ImportError:
25 except ImportError:
26 try:
26 try:
27 import sha
27 import sha
28 sha.sha # silence unused import warning
28 sha.sha # silence unused import warning
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 zlib.compressobj # silence unused import warning
35 zlib.compressobj # silence unused import warning
36 except ImportError:
36 except ImportError:
37 raise SystemExit(
37 raise SystemExit(
38 "Couldn't import standard zlib (incomplete Python install).")
38 "Couldn't import standard zlib (incomplete Python install).")
39
39
40 # The base IronPython distribution (as of 2.7.1) doesn't support bz2
40 # The base IronPython distribution (as of 2.7.1) doesn't support bz2
41 isironpython = False
41 isironpython = False
42 try:
42 try:
43 isironpython = (platform.python_implementation()
43 isironpython = (platform.python_implementation()
44 .lower().find("ironpython") != -1)
44 .lower().find("ironpython") != -1)
45 except AttributeError:
45 except AttributeError:
46 pass
46 pass
47
47
48 if isironpython:
48 if isironpython:
49 sys.stderr.write("warning: IronPython detected (no bz2 support)\n")
49 sys.stderr.write("warning: IronPython detected (no bz2 support)\n")
50 else:
50 else:
51 try:
51 try:
52 import bz2
52 import bz2
53 bz2.BZ2Compressor # silence unused import warning
53 bz2.BZ2Compressor # silence unused import warning
54 except ImportError:
54 except ImportError:
55 raise SystemExit(
55 raise SystemExit(
56 "Couldn't import standard bz2 (incomplete Python install).")
56 "Couldn't import standard bz2 (incomplete Python install).")
57
57
58 ispypy = "PyPy" in sys.version
58 ispypy = "PyPy" in sys.version
59
59
60 import ctypes
60 import ctypes
61 import os, stat, subprocess, time
61 import os, stat, subprocess, time
62 import re
62 import re
63 import shutil
63 import shutil
64 import tempfile
64 import tempfile
65 from distutils import log
65 from distutils import log
66 if 'FORCE_SETUPTOOLS' in os.environ:
66 if 'FORCE_SETUPTOOLS' in os.environ:
67 from setuptools import setup
67 from setuptools import setup
68 else:
68 else:
69 from distutils.core import setup
69 from distutils.core import setup
70 from distutils.core import Command, Extension
70 from distutils.core import Command, Extension
71 from distutils.dist import Distribution
71 from distutils.dist import Distribution
72 from distutils.command.build import build
72 from distutils.command.build import build
73 from distutils.command.build_ext import build_ext
73 from distutils.command.build_ext import build_ext
74 from distutils.command.build_py import build_py
74 from distutils.command.build_py import build_py
75 from distutils.command.build_scripts import build_scripts
75 from distutils.command.build_scripts import build_scripts
76 from distutils.command.install_lib import install_lib
76 from distutils.command.install_lib import install_lib
77 from distutils.command.install_scripts import install_scripts
77 from distutils.command.install_scripts import install_scripts
78 from distutils.spawn import spawn, find_executable
78 from distutils.spawn import spawn, find_executable
79 from distutils import file_util
79 from distutils import file_util
80 from distutils.errors import (
80 from distutils.errors import (
81 CCompilerError,
81 CCompilerError,
82 DistutilsError,
82 DistutilsError,
83 DistutilsExecError,
83 DistutilsExecError,
84 )
84 )
85 from distutils.sysconfig import get_python_inc, get_config_var
85 from distutils.sysconfig import get_python_inc, get_config_var
86 from distutils.version import StrictVersion
86 from distutils.version import StrictVersion
87
87
88 scripts = ['hg']
88 scripts = ['hg']
89 if os.name == 'nt':
89 if os.name == 'nt':
90 # We remove hg.bat if we are able to build hg.exe.
90 # We remove hg.bat if we are able to build hg.exe.
91 scripts.append('contrib/win32/hg.bat')
91 scripts.append('contrib/win32/hg.bat')
92
92
93 # simplified version of distutils.ccompiler.CCompiler.has_function
93 # simplified version of distutils.ccompiler.CCompiler.has_function
94 # that actually removes its temporary files.
94 # that actually removes its temporary files.
95 def hasfunction(cc, funcname):
95 def hasfunction(cc, funcname):
96 tmpdir = tempfile.mkdtemp(prefix='hg-install-')
96 tmpdir = tempfile.mkdtemp(prefix='hg-install-')
97 devnull = oldstderr = None
97 devnull = oldstderr = None
98 try:
98 try:
99 fname = os.path.join(tmpdir, 'funcname.c')
99 fname = os.path.join(tmpdir, 'funcname.c')
100 f = open(fname, 'w')
100 f = open(fname, 'w')
101 f.write('int main(void) {\n')
101 f.write('int main(void) {\n')
102 f.write(' %s();\n' % funcname)
102 f.write(' %s();\n' % funcname)
103 f.write('}\n')
103 f.write('}\n')
104 f.close()
104 f.close()
105 # Redirect stderr to /dev/null to hide any error messages
105 # Redirect stderr to /dev/null to hide any error messages
106 # from the compiler.
106 # from the compiler.
107 # This will have to be changed if we ever have to check
107 # This will have to be changed if we ever have to check
108 # for a function on Windows.
108 # for a function on Windows.
109 devnull = open('/dev/null', 'w')
109 devnull = open('/dev/null', 'w')
110 oldstderr = os.dup(sys.stderr.fileno())
110 oldstderr = os.dup(sys.stderr.fileno())
111 os.dup2(devnull.fileno(), sys.stderr.fileno())
111 os.dup2(devnull.fileno(), sys.stderr.fileno())
112 objects = cc.compile([fname], output_dir=tmpdir)
112 objects = cc.compile([fname], output_dir=tmpdir)
113 cc.link_executable(objects, os.path.join(tmpdir, "a.out"))
113 cc.link_executable(objects, os.path.join(tmpdir, "a.out"))
114 return True
114 return True
115 except Exception:
115 except Exception:
116 return False
116 return False
117 finally:
117 finally:
118 if oldstderr is not None:
118 if oldstderr is not None:
119 os.dup2(oldstderr, sys.stderr.fileno())
119 os.dup2(oldstderr, sys.stderr.fileno())
120 if devnull is not None:
120 if devnull is not None:
121 devnull.close()
121 devnull.close()
122 shutil.rmtree(tmpdir)
122 shutil.rmtree(tmpdir)
123
123
124 # py2exe needs to be installed to work
124 # py2exe needs to be installed to work
125 try:
125 try:
126 import py2exe
126 import py2exe
127 py2exe.Distribution # silence unused import warning
127 py2exe.Distribution # silence unused import warning
128 py2exeloaded = True
128 py2exeloaded = True
129 # import py2exe's patched Distribution class
129 # import py2exe's patched Distribution class
130 from distutils.core import Distribution
130 from distutils.core import Distribution
131 except ImportError:
131 except ImportError:
132 py2exeloaded = False
132 py2exeloaded = False
133
133
134 def runcmd(cmd, env):
134 def runcmd(cmd, env):
135 if (sys.platform == 'plan9'
135 if (sys.platform == 'plan9'
136 and (sys.version_info[0] == 2 and sys.version_info[1] < 7)):
136 and (sys.version_info[0] == 2 and sys.version_info[1] < 7)):
137 # subprocess kludge to work around issues in half-baked Python
137 # subprocess kludge to work around issues in half-baked Python
138 # ports, notably bichued/python:
138 # ports, notably bichued/python:
139 _, out, err = os.popen3(cmd)
139 _, out, err = os.popen3(cmd)
140 return str(out), str(err)
140 return str(out), str(err)
141 else:
141 else:
142 p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
142 p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
143 stderr=subprocess.PIPE, env=env)
143 stderr=subprocess.PIPE, env=env)
144 out, err = p.communicate()
144 out, err = p.communicate()
145 return out, err
145 return out, err
146
146
147 def runhg(cmd, env):
147 def runhg(cmd, env):
148 out, err = runcmd(cmd, env)
148 out, err = runcmd(cmd, env)
149 # If root is executing setup.py, but the repository is owned by
149 # If root is executing setup.py, but the repository is owned by
150 # another user (as in "sudo python setup.py install") we will get
150 # another user (as in "sudo python setup.py install") we will get
151 # trust warnings since the .hg/hgrc file is untrusted. That is
151 # trust warnings since the .hg/hgrc file is untrusted. That is
152 # fine, we don't want to load it anyway. Python may warn about
152 # fine, we don't want to load it anyway. Python may warn about
153 # a missing __init__.py in mercurial/locale, we also ignore that.
153 # a missing __init__.py in mercurial/locale, we also ignore that.
154 err = [e for e in err.splitlines()
154 err = [e for e in err.splitlines()
155 if not e.startswith(b'not trusting file') \
155 if not e.startswith(b'not trusting file') \
156 and not e.startswith(b'warning: Not importing') \
156 and not e.startswith(b'warning: Not importing') \
157 and not e.startswith(b'obsolete feature not enabled')]
157 and not e.startswith(b'obsolete feature not enabled')]
158 if err:
158 if err:
159 printf("stderr from '%s':" % (' '.join(cmd)), file=sys.stderr)
159 printf("stderr from '%s':" % (' '.join(cmd)), file=sys.stderr)
160 printf(b'\n'.join([b' ' + e for e in err]), file=sys.stderr)
160 printf(b'\n'.join([b' ' + e for e in err]), file=sys.stderr)
161 return ''
161 return ''
162 return out
162 return out
163
163
164 version = ''
164 version = ''
165
165
166 # Execute hg out of this directory with a custom environment which takes care
166 # Execute hg out of this directory with a custom environment which takes care
167 # to not use any hgrc files and do no localization.
167 # to not use any hgrc files and do no localization.
168 env = {'HGMODULEPOLICY': 'py',
168 env = {'HGMODULEPOLICY': 'py',
169 'HGRCPATH': '',
169 'HGRCPATH': '',
170 'LANGUAGE': 'C'}
170 'LANGUAGE': 'C'}
171 if 'LD_LIBRARY_PATH' in os.environ:
171 if 'LD_LIBRARY_PATH' in os.environ:
172 env['LD_LIBRARY_PATH'] = os.environ['LD_LIBRARY_PATH']
172 env['LD_LIBRARY_PATH'] = os.environ['LD_LIBRARY_PATH']
173 if 'SystemRoot' in os.environ:
173 if 'SystemRoot' in os.environ:
174 # Copy SystemRoot into the custom environment for Python 2.6
174 # Copy SystemRoot into the custom environment for Python 2.6
175 # under Windows. Otherwise, the subprocess will fail with
175 # under Windows. Otherwise, the subprocess will fail with
176 # error 0xc0150004. See: http://bugs.python.org/issue3440
176 # error 0xc0150004. See: http://bugs.python.org/issue3440
177 env['SystemRoot'] = os.environ['SystemRoot']
177 env['SystemRoot'] = os.environ['SystemRoot']
178
178
179 if os.path.isdir('.hg'):
179 if os.path.isdir('.hg'):
180 cmd = [sys.executable, 'hg', 'log', '-r', '.', '--template', '{tags}\n']
180 cmd = [sys.executable, 'hg', 'log', '-r', '.', '--template', '{tags}\n']
181 numerictags = [t for t in runhg(cmd, env).split() if t[0].isdigit()]
181 numerictags = [t for t in runhg(cmd, env).split() if t[0].isdigit()]
182 hgid = runhg([sys.executable, 'hg', 'id', '-i'], env).strip()
182 hgid = runhg([sys.executable, 'hg', 'id', '-i'], env).strip()
183 if numerictags: # tag(s) found
183 if numerictags: # tag(s) found
184 version = numerictags[-1]
184 version = numerictags[-1]
185 if hgid.endswith('+'): # propagate the dirty status to the tag
185 if hgid.endswith('+'): # propagate the dirty status to the tag
186 version += '+'
186 version += '+'
187 else: # no tag found
187 else: # no tag found
188 ltagcmd = [sys.executable, 'hg', 'parents', '--template',
188 ltagcmd = [sys.executable, 'hg', 'parents', '--template',
189 '{latesttag}']
189 '{latesttag}']
190 ltag = runhg(ltagcmd, env)
190 ltag = runhg(ltagcmd, env)
191 changessincecmd = [sys.executable, 'hg', 'log', '-T', 'x\n', '-r',
191 changessincecmd = [sys.executable, 'hg', 'log', '-T', 'x\n', '-r',
192 "only(.,'%s')" % ltag]
192 "only(.,'%s')" % ltag]
193 changessince = len(runhg(changessincecmd, env).splitlines())
193 changessince = len(runhg(changessincecmd, env).splitlines())
194 version = '%s+%s-%s' % (ltag, changessince, hgid)
194 version = '%s+%s-%s' % (ltag, changessince, hgid)
195 if version.endswith('+'):
195 if version.endswith('+'):
196 version += time.strftime('%Y%m%d')
196 version += time.strftime('%Y%m%d')
197 elif os.path.exists('.hg_archival.txt'):
197 elif os.path.exists('.hg_archival.txt'):
198 kw = dict([[t.strip() for t in l.split(':', 1)]
198 kw = dict([[t.strip() for t in l.split(':', 1)]
199 for l in open('.hg_archival.txt')])
199 for l in open('.hg_archival.txt')])
200 if 'tag' in kw:
200 if 'tag' in kw:
201 version = kw['tag']
201 version = kw['tag']
202 elif 'latesttag' in kw:
202 elif 'latesttag' in kw:
203 if 'changessincelatesttag' in kw:
203 if 'changessincelatesttag' in kw:
204 version = '%(latesttag)s+%(changessincelatesttag)s-%(node).12s' % kw
204 version = '%(latesttag)s+%(changessincelatesttag)s-%(node).12s' % kw
205 else:
205 else:
206 version = '%(latesttag)s+%(latesttagdistance)s-%(node).12s' % kw
206 version = '%(latesttag)s+%(latesttagdistance)s-%(node).12s' % kw
207 else:
207 else:
208 version = kw.get('node', '')[:12]
208 version = kw.get('node', '')[:12]
209
209
210 if version:
210 if version:
211 with open("mercurial/__version__.py", "w") as f:
211 with open("mercurial/__version__.py", "w") as f:
212 f.write('# this file is autogenerated by setup.py\n')
212 f.write('# this file is autogenerated by setup.py\n')
213 f.write('version = "%s"\n' % version)
213 f.write('version = "%s"\n' % version)
214
214
215 try:
215 try:
216 oldpolicy = os.environ.get('HGMODULEPOLICY', None)
216 oldpolicy = os.environ.get('HGMODULEPOLICY', None)
217 os.environ['HGMODULEPOLICY'] = 'py'
217 os.environ['HGMODULEPOLICY'] = 'py'
218 from mercurial import __version__
218 from mercurial import __version__
219 version = __version__.version
219 version = __version__.version
220 except ImportError:
220 except ImportError:
221 version = 'unknown'
221 version = 'unknown'
222 finally:
222 finally:
223 if oldpolicy is None:
223 if oldpolicy is None:
224 del os.environ['HGMODULEPOLICY']
224 del os.environ['HGMODULEPOLICY']
225 else:
225 else:
226 os.environ['HGMODULEPOLICY'] = oldpolicy
226 os.environ['HGMODULEPOLICY'] = oldpolicy
227
227
228 class hgbuild(build):
228 class hgbuild(build):
229 # Insert hgbuildmo first so that files in mercurial/locale/ are found
229 # Insert hgbuildmo first so that files in mercurial/locale/ are found
230 # when build_py is run next.
230 # when build_py is run next.
231 sub_commands = [('build_mo', None)] + build.sub_commands
231 sub_commands = [('build_mo', None)] + build.sub_commands
232
232
233 class hgbuildmo(build):
233 class hgbuildmo(build):
234
234
235 description = "build translations (.mo files)"
235 description = "build translations (.mo files)"
236
236
237 def run(self):
237 def run(self):
238 if not find_executable('msgfmt'):
238 if not find_executable('msgfmt'):
239 self.warn("could not find msgfmt executable, no translations "
239 self.warn("could not find msgfmt executable, no translations "
240 "will be built")
240 "will be built")
241 return
241 return
242
242
243 podir = 'i18n'
243 podir = 'i18n'
244 if not os.path.isdir(podir):
244 if not os.path.isdir(podir):
245 self.warn("could not find %s/ directory" % podir)
245 self.warn("could not find %s/ directory" % podir)
246 return
246 return
247
247
248 join = os.path.join
248 join = os.path.join
249 for po in os.listdir(podir):
249 for po in os.listdir(podir):
250 if not po.endswith('.po'):
250 if not po.endswith('.po'):
251 continue
251 continue
252 pofile = join(podir, po)
252 pofile = join(podir, po)
253 modir = join('locale', po[:-3], 'LC_MESSAGES')
253 modir = join('locale', po[:-3], 'LC_MESSAGES')
254 mofile = join(modir, 'hg.mo')
254 mofile = join(modir, 'hg.mo')
255 mobuildfile = join('mercurial', mofile)
255 mobuildfile = join('mercurial', mofile)
256 cmd = ['msgfmt', '-v', '-o', mobuildfile, pofile]
256 cmd = ['msgfmt', '-v', '-o', mobuildfile, pofile]
257 if sys.platform != 'sunos5':
257 if sys.platform != 'sunos5':
258 # msgfmt on Solaris does not know about -c
258 # msgfmt on Solaris does not know about -c
259 cmd.append('-c')
259 cmd.append('-c')
260 self.mkpath(join('mercurial', modir))
260 self.mkpath(join('mercurial', modir))
261 self.make_file([pofile], mobuildfile, spawn, (cmd,))
261 self.make_file([pofile], mobuildfile, spawn, (cmd,))
262
262
263
263
264 class hgdist(Distribution):
264 class hgdist(Distribution):
265 pure = ispypy
265 pure = False
266 cffi = ispypy
266
267
267 global_options = Distribution.global_options + \
268 global_options = Distribution.global_options + \
268 [('pure', None, "use pure (slow) Python "
269 [('pure', None, "use pure (slow) Python "
269 "code instead of C extensions"),
270 "code instead of C extensions"),
270 ]
271 ]
271
272
272 def has_ext_modules(self):
273 def has_ext_modules(self):
273 # self.ext_modules is emptied in hgbuildpy.finalize_options which is
274 # self.ext_modules is emptied in hgbuildpy.finalize_options which is
274 # too late for some cases
275 # too late for some cases
275 return not self.pure and Distribution.has_ext_modules(self)
276 return not self.pure and Distribution.has_ext_modules(self)
276
277
277 class hgbuildext(build_ext):
278 class hgbuildext(build_ext):
278
279
279 def build_extension(self, ext):
280 def build_extension(self, ext):
280 try:
281 try:
281 build_ext.build_extension(self, ext)
282 build_ext.build_extension(self, ext)
282 except CCompilerError:
283 except CCompilerError:
283 if not getattr(ext, 'optional', False):
284 if not getattr(ext, 'optional', False):
284 raise
285 raise
285 log.warn("Failed to build optional extension '%s' (skipping)",
286 log.warn("Failed to build optional extension '%s' (skipping)",
286 ext.name)
287 ext.name)
287
288
288 class hgbuildscripts(build_scripts):
289 class hgbuildscripts(build_scripts):
289 def run(self):
290 def run(self):
290 if os.name != 'nt' or self.distribution.pure:
291 if os.name != 'nt' or self.distribution.pure:
291 return build_scripts.run(self)
292 return build_scripts.run(self)
292
293
293 exebuilt = False
294 exebuilt = False
294 try:
295 try:
295 self.run_command('build_hgexe')
296 self.run_command('build_hgexe')
296 exebuilt = True
297 exebuilt = True
297 except (DistutilsError, CCompilerError):
298 except (DistutilsError, CCompilerError):
298 log.warn('failed to build optional hg.exe')
299 log.warn('failed to build optional hg.exe')
299
300
300 if exebuilt:
301 if exebuilt:
301 # Copying hg.exe to the scripts build directory ensures it is
302 # Copying hg.exe to the scripts build directory ensures it is
302 # installed by the install_scripts command.
303 # installed by the install_scripts command.
303 hgexecommand = self.get_finalized_command('build_hgexe')
304 hgexecommand = self.get_finalized_command('build_hgexe')
304 dest = os.path.join(self.build_dir, 'hg.exe')
305 dest = os.path.join(self.build_dir, 'hg.exe')
305 self.mkpath(self.build_dir)
306 self.mkpath(self.build_dir)
306 self.copy_file(hgexecommand.hgexepath, dest)
307 self.copy_file(hgexecommand.hgexepath, dest)
307
308
308 # Remove hg.bat because it is redundant with hg.exe.
309 # Remove hg.bat because it is redundant with hg.exe.
309 self.scripts.remove('contrib/win32/hg.bat')
310 self.scripts.remove('contrib/win32/hg.bat')
310
311
311 return build_scripts.run(self)
312 return build_scripts.run(self)
312
313
313 class hgbuildpy(build_py):
314 class hgbuildpy(build_py):
314 def finalize_options(self):
315 def finalize_options(self):
315 build_py.finalize_options(self)
316 build_py.finalize_options(self)
316
317
317 if self.distribution.pure:
318 if self.distribution.pure:
318 self.distribution.ext_modules = []
319 self.distribution.ext_modules = []
320 elif self.distribution.cffi:
321 exts = []
322 # cffi modules go here
323 self.distribution.ext_modules = exts
319 else:
324 else:
320 h = os.path.join(get_python_inc(), 'Python.h')
325 h = os.path.join(get_python_inc(), 'Python.h')
321 if not os.path.exists(h):
326 if not os.path.exists(h):
322 raise SystemExit('Python headers are required to build '
327 raise SystemExit('Python headers are required to build '
323 'Mercurial but weren\'t found in %s' % h)
328 'Mercurial but weren\'t found in %s' % h)
324
329
325 def run(self):
330 def run(self):
326 if self.distribution.pure:
331 if self.distribution.pure:
327 modulepolicy = 'py'
332 modulepolicy = 'py'
328 else:
333 else:
329 modulepolicy = 'c'
334 modulepolicy = 'c'
330 with open("mercurial/__modulepolicy__.py", "w") as f:
335 with open("mercurial/__modulepolicy__.py", "w") as f:
331 f.write('# this file is autogenerated by setup.py\n')
336 f.write('# this file is autogenerated by setup.py\n')
332 f.write('modulepolicy = "%s"\n' % modulepolicy)
337 f.write('modulepolicy = "%s"\n' % modulepolicy)
333
338
334 build_py.run(self)
339 build_py.run(self)
335
340
336 class buildhgextindex(Command):
341 class buildhgextindex(Command):
337 description = 'generate prebuilt index of hgext (for frozen package)'
342 description = 'generate prebuilt index of hgext (for frozen package)'
338 user_options = []
343 user_options = []
339 _indexfilename = 'hgext/__index__.py'
344 _indexfilename = 'hgext/__index__.py'
340
345
341 def initialize_options(self):
346 def initialize_options(self):
342 pass
347 pass
343
348
344 def finalize_options(self):
349 def finalize_options(self):
345 pass
350 pass
346
351
347 def run(self):
352 def run(self):
348 if os.path.exists(self._indexfilename):
353 if os.path.exists(self._indexfilename):
349 with open(self._indexfilename, 'w') as f:
354 with open(self._indexfilename, 'w') as f:
350 f.write('# empty\n')
355 f.write('# empty\n')
351
356
352 # here no extension enabled, disabled() lists up everything
357 # here no extension enabled, disabled() lists up everything
353 code = ('import pprint; from mercurial import extensions; '
358 code = ('import pprint; from mercurial import extensions; '
354 'pprint.pprint(extensions.disabled())')
359 'pprint.pprint(extensions.disabled())')
355 out, err = runcmd([sys.executable, '-c', code], env)
360 out, err = runcmd([sys.executable, '-c', code], env)
356 if err:
361 if err:
357 raise DistutilsExecError(err)
362 raise DistutilsExecError(err)
358
363
359 with open(self._indexfilename, 'w') as f:
364 with open(self._indexfilename, 'w') as f:
360 f.write('# this file is autogenerated by setup.py\n')
365 f.write('# this file is autogenerated by setup.py\n')
361 f.write('docs = ')
366 f.write('docs = ')
362 f.write(out)
367 f.write(out)
363
368
364 class buildhgexe(build_ext):
369 class buildhgexe(build_ext):
365 description = 'compile hg.exe from mercurial/exewrapper.c'
370 description = 'compile hg.exe from mercurial/exewrapper.c'
366
371
367 def build_extensions(self):
372 def build_extensions(self):
368 if os.name != 'nt':
373 if os.name != 'nt':
369 return
374 return
370 if isinstance(self.compiler, HackedMingw32CCompiler):
375 if isinstance(self.compiler, HackedMingw32CCompiler):
371 self.compiler.compiler_so = self.compiler.compiler # no -mdll
376 self.compiler.compiler_so = self.compiler.compiler # no -mdll
372 self.compiler.dll_libraries = [] # no -lmsrvc90
377 self.compiler.dll_libraries = [] # no -lmsrvc90
373
378
374 # Different Python installs can have different Python library
379 # Different Python installs can have different Python library
375 # names. e.g. the official CPython distribution uses pythonXY.dll
380 # names. e.g. the official CPython distribution uses pythonXY.dll
376 # and MinGW uses libpythonX.Y.dll.
381 # and MinGW uses libpythonX.Y.dll.
377 _kernel32 = ctypes.windll.kernel32
382 _kernel32 = ctypes.windll.kernel32
378 _kernel32.GetModuleFileNameA.argtypes = [ctypes.c_void_p,
383 _kernel32.GetModuleFileNameA.argtypes = [ctypes.c_void_p,
379 ctypes.c_void_p,
384 ctypes.c_void_p,
380 ctypes.c_ulong]
385 ctypes.c_ulong]
381 _kernel32.GetModuleFileNameA.restype = ctypes.c_ulong
386 _kernel32.GetModuleFileNameA.restype = ctypes.c_ulong
382 size = 1000
387 size = 1000
383 buf = ctypes.create_string_buffer(size + 1)
388 buf = ctypes.create_string_buffer(size + 1)
384 filelen = _kernel32.GetModuleFileNameA(sys.dllhandle, ctypes.byref(buf),
389 filelen = _kernel32.GetModuleFileNameA(sys.dllhandle, ctypes.byref(buf),
385 size)
390 size)
386
391
387 if filelen > 0 and filelen != size:
392 if filelen > 0 and filelen != size:
388 dllbasename = os.path.basename(buf.value)
393 dllbasename = os.path.basename(buf.value)
389 if not dllbasename.lower().endswith('.dll'):
394 if not dllbasename.lower().endswith('.dll'):
390 raise SystemExit('Python DLL does not end with .dll: %s' %
395 raise SystemExit('Python DLL does not end with .dll: %s' %
391 dllbasename)
396 dllbasename)
392 pythonlib = dllbasename[:-4]
397 pythonlib = dllbasename[:-4]
393 else:
398 else:
394 log.warn('could not determine Python DLL filename; '
399 log.warn('could not determine Python DLL filename; '
395 'assuming pythonXY')
400 'assuming pythonXY')
396
401
397 hv = sys.hexversion
402 hv = sys.hexversion
398 pythonlib = 'python%d%d' % (hv >> 24, (hv >> 16) & 0xff)
403 pythonlib = 'python%d%d' % (hv >> 24, (hv >> 16) & 0xff)
399
404
400 log.info('using %s as Python library name' % pythonlib)
405 log.info('using %s as Python library name' % pythonlib)
401 with open('mercurial/hgpythonlib.h', 'wb') as f:
406 with open('mercurial/hgpythonlib.h', 'wb') as f:
402 f.write('/* this file is autogenerated by setup.py */\n')
407 f.write('/* this file is autogenerated by setup.py */\n')
403 f.write('#define HGPYTHONLIB "%s"\n' % pythonlib)
408 f.write('#define HGPYTHONLIB "%s"\n' % pythonlib)
404 objects = self.compiler.compile(['mercurial/exewrapper.c'],
409 objects = self.compiler.compile(['mercurial/exewrapper.c'],
405 output_dir=self.build_temp)
410 output_dir=self.build_temp)
406 dir = os.path.dirname(self.get_ext_fullpath('dummy'))
411 dir = os.path.dirname(self.get_ext_fullpath('dummy'))
407 target = os.path.join(dir, 'hg')
412 target = os.path.join(dir, 'hg')
408 self.compiler.link_executable(objects, target,
413 self.compiler.link_executable(objects, target,
409 libraries=[],
414 libraries=[],
410 output_dir=self.build_temp)
415 output_dir=self.build_temp)
411
416
412 @property
417 @property
413 def hgexepath(self):
418 def hgexepath(self):
414 dir = os.path.dirname(self.get_ext_fullpath('dummy'))
419 dir = os.path.dirname(self.get_ext_fullpath('dummy'))
415 return os.path.join(self.build_temp, dir, 'hg.exe')
420 return os.path.join(self.build_temp, dir, 'hg.exe')
416
421
417 class hginstalllib(install_lib):
422 class hginstalllib(install_lib):
418 '''
423 '''
419 This is a specialization of install_lib that replaces the copy_file used
424 This is a specialization of install_lib that replaces the copy_file used
420 there so that it supports setting the mode of files after copying them,
425 there so that it supports setting the mode of files after copying them,
421 instead of just preserving the mode that the files originally had. If your
426 instead of just preserving the mode that the files originally had. If your
422 system has a umask of something like 027, preserving the permissions when
427 system has a umask of something like 027, preserving the permissions when
423 copying will lead to a broken install.
428 copying will lead to a broken install.
424
429
425 Note that just passing keep_permissions=False to copy_file would be
430 Note that just passing keep_permissions=False to copy_file would be
426 insufficient, as it might still be applying a umask.
431 insufficient, as it might still be applying a umask.
427 '''
432 '''
428
433
429 def run(self):
434 def run(self):
430 realcopyfile = file_util.copy_file
435 realcopyfile = file_util.copy_file
431 def copyfileandsetmode(*args, **kwargs):
436 def copyfileandsetmode(*args, **kwargs):
432 src, dst = args[0], args[1]
437 src, dst = args[0], args[1]
433 dst, copied = realcopyfile(*args, **kwargs)
438 dst, copied = realcopyfile(*args, **kwargs)
434 if copied:
439 if copied:
435 st = os.stat(src)
440 st = os.stat(src)
436 # Persist executable bit (apply it to group and other if user
441 # Persist executable bit (apply it to group and other if user
437 # has it)
442 # has it)
438 if st[stat.ST_MODE] & stat.S_IXUSR:
443 if st[stat.ST_MODE] & stat.S_IXUSR:
439 setmode = int('0755', 8)
444 setmode = int('0755', 8)
440 else:
445 else:
441 setmode = int('0644', 8)
446 setmode = int('0644', 8)
442 m = stat.S_IMODE(st[stat.ST_MODE])
447 m = stat.S_IMODE(st[stat.ST_MODE])
443 m = (m & ~int('0777', 8)) | setmode
448 m = (m & ~int('0777', 8)) | setmode
444 os.chmod(dst, m)
449 os.chmod(dst, m)
445 file_util.copy_file = copyfileandsetmode
450 file_util.copy_file = copyfileandsetmode
446 try:
451 try:
447 install_lib.run(self)
452 install_lib.run(self)
448 finally:
453 finally:
449 file_util.copy_file = realcopyfile
454 file_util.copy_file = realcopyfile
450
455
451 class hginstallscripts(install_scripts):
456 class hginstallscripts(install_scripts):
452 '''
457 '''
453 This is a specialization of install_scripts that replaces the @LIBDIR@ with
458 This is a specialization of install_scripts that replaces the @LIBDIR@ with
454 the configured directory for modules. If possible, the path is made relative
459 the configured directory for modules. If possible, the path is made relative
455 to the directory for scripts.
460 to the directory for scripts.
456 '''
461 '''
457
462
458 def initialize_options(self):
463 def initialize_options(self):
459 install_scripts.initialize_options(self)
464 install_scripts.initialize_options(self)
460
465
461 self.install_lib = None
466 self.install_lib = None
462
467
463 def finalize_options(self):
468 def finalize_options(self):
464 install_scripts.finalize_options(self)
469 install_scripts.finalize_options(self)
465 self.set_undefined_options('install',
470 self.set_undefined_options('install',
466 ('install_lib', 'install_lib'))
471 ('install_lib', 'install_lib'))
467
472
468 def run(self):
473 def run(self):
469 install_scripts.run(self)
474 install_scripts.run(self)
470
475
471 # It only makes sense to replace @LIBDIR@ with the install path if
476 # It only makes sense to replace @LIBDIR@ with the install path if
472 # the install path is known. For wheels, the logic below calculates
477 # the install path is known. For wheels, the logic below calculates
473 # the libdir to be "../..". This is because the internal layout of a
478 # the libdir to be "../..". This is because the internal layout of a
474 # wheel archive looks like:
479 # wheel archive looks like:
475 #
480 #
476 # mercurial-3.6.1.data/scripts/hg
481 # mercurial-3.6.1.data/scripts/hg
477 # mercurial/__init__.py
482 # mercurial/__init__.py
478 #
483 #
479 # When installing wheels, the subdirectories of the "<pkg>.data"
484 # When installing wheels, the subdirectories of the "<pkg>.data"
480 # directory are translated to system local paths and files therein
485 # directory are translated to system local paths and files therein
481 # are copied in place. The mercurial/* files are installed into the
486 # are copied in place. The mercurial/* files are installed into the
482 # site-packages directory. However, the site-packages directory
487 # site-packages directory. However, the site-packages directory
483 # isn't known until wheel install time. This means we have no clue
488 # isn't known until wheel install time. This means we have no clue
484 # at wheel generation time what the installed site-packages directory
489 # at wheel generation time what the installed site-packages directory
485 # will be. And, wheels don't appear to provide the ability to register
490 # will be. And, wheels don't appear to provide the ability to register
486 # custom code to run during wheel installation. This all means that
491 # custom code to run during wheel installation. This all means that
487 # we can't reliably set the libdir in wheels: the default behavior
492 # we can't reliably set the libdir in wheels: the default behavior
488 # of looking in sys.path must do.
493 # of looking in sys.path must do.
489
494
490 if (os.path.splitdrive(self.install_dir)[0] !=
495 if (os.path.splitdrive(self.install_dir)[0] !=
491 os.path.splitdrive(self.install_lib)[0]):
496 os.path.splitdrive(self.install_lib)[0]):
492 # can't make relative paths from one drive to another, so use an
497 # can't make relative paths from one drive to another, so use an
493 # absolute path instead
498 # absolute path instead
494 libdir = self.install_lib
499 libdir = self.install_lib
495 else:
500 else:
496 common = os.path.commonprefix((self.install_dir, self.install_lib))
501 common = os.path.commonprefix((self.install_dir, self.install_lib))
497 rest = self.install_dir[len(common):]
502 rest = self.install_dir[len(common):]
498 uplevel = len([n for n in os.path.split(rest) if n])
503 uplevel = len([n for n in os.path.split(rest) if n])
499
504
500 libdir = uplevel * ('..' + os.sep) + self.install_lib[len(common):]
505 libdir = uplevel * ('..' + os.sep) + self.install_lib[len(common):]
501
506
502 for outfile in self.outfiles:
507 for outfile in self.outfiles:
503 with open(outfile, 'rb') as fp:
508 with open(outfile, 'rb') as fp:
504 data = fp.read()
509 data = fp.read()
505
510
506 # skip binary files
511 # skip binary files
507 if b'\0' in data:
512 if b'\0' in data:
508 continue
513 continue
509
514
510 # During local installs, the shebang will be rewritten to the final
515 # During local installs, the shebang will be rewritten to the final
511 # install path. During wheel packaging, the shebang has a special
516 # install path. During wheel packaging, the shebang has a special
512 # value.
517 # value.
513 if data.startswith(b'#!python'):
518 if data.startswith(b'#!python'):
514 log.info('not rewriting @LIBDIR@ in %s because install path '
519 log.info('not rewriting @LIBDIR@ in %s because install path '
515 'not known' % outfile)
520 'not known' % outfile)
516 continue
521 continue
517
522
518 data = data.replace(b'@LIBDIR@', libdir.encode(libdir_escape))
523 data = data.replace(b'@LIBDIR@', libdir.encode(libdir_escape))
519 with open(outfile, 'wb') as fp:
524 with open(outfile, 'wb') as fp:
520 fp.write(data)
525 fp.write(data)
521
526
522 cmdclass = {'build': hgbuild,
527 cmdclass = {'build': hgbuild,
523 'build_mo': hgbuildmo,
528 'build_mo': hgbuildmo,
524 'build_ext': hgbuildext,
529 'build_ext': hgbuildext,
525 'build_py': hgbuildpy,
530 'build_py': hgbuildpy,
526 'build_scripts': hgbuildscripts,
531 'build_scripts': hgbuildscripts,
527 'build_hgextindex': buildhgextindex,
532 'build_hgextindex': buildhgextindex,
528 'install_lib': hginstalllib,
533 'install_lib': hginstalllib,
529 'install_scripts': hginstallscripts,
534 'install_scripts': hginstallscripts,
530 'build_hgexe': buildhgexe,
535 'build_hgexe': buildhgexe,
531 }
536 }
532
537
533 packages = ['mercurial', 'mercurial.hgweb', 'mercurial.httpclient',
538 packages = ['mercurial', 'mercurial.hgweb', 'mercurial.httpclient',
534 'mercurial.pure',
539 'mercurial.pure',
535 'hgext', 'hgext.convert', 'hgext.fsmonitor',
540 'hgext', 'hgext.convert', 'hgext.fsmonitor',
536 'hgext.fsmonitor.pywatchman', 'hgext.highlight',
541 'hgext.fsmonitor.pywatchman', 'hgext.highlight',
537 'hgext.largefiles', 'hgext.zeroconf', 'hgext3rd']
542 'hgext.largefiles', 'hgext.zeroconf', 'hgext3rd']
538
543
539 common_depends = ['mercurial/bitmanipulation.h',
544 common_depends = ['mercurial/bitmanipulation.h',
540 'mercurial/compat.h',
545 'mercurial/compat.h',
541 'mercurial/util.h']
546 'mercurial/util.h']
542
547
543 osutil_ldflags = []
548 osutil_ldflags = []
544
549
545 if sys.platform == 'darwin':
550 if sys.platform == 'darwin':
546 osutil_ldflags += ['-framework', 'ApplicationServices']
551 osutil_ldflags += ['-framework', 'ApplicationServices']
547
552
548 extmodules = [
553 extmodules = [
549 Extension('mercurial.base85', ['mercurial/base85.c'],
554 Extension('mercurial.base85', ['mercurial/base85.c'],
550 depends=common_depends),
555 depends=common_depends),
551 Extension('mercurial.bdiff', ['mercurial/bdiff.c'],
556 Extension('mercurial.bdiff', ['mercurial/bdiff.c'],
552 depends=common_depends),
557 depends=common_depends),
553 Extension('mercurial.diffhelpers', ['mercurial/diffhelpers.c'],
558 Extension('mercurial.diffhelpers', ['mercurial/diffhelpers.c'],
554 depends=common_depends),
559 depends=common_depends),
555 Extension('mercurial.mpatch', ['mercurial/mpatch.c'],
560 Extension('mercurial.mpatch', ['mercurial/mpatch.c'],
556 depends=common_depends),
561 depends=common_depends),
557 Extension('mercurial.parsers', ['mercurial/dirs.c',
562 Extension('mercurial.parsers', ['mercurial/dirs.c',
558 'mercurial/manifest.c',
563 'mercurial/manifest.c',
559 'mercurial/parsers.c',
564 'mercurial/parsers.c',
560 'mercurial/pathencode.c'],
565 'mercurial/pathencode.c'],
561 depends=common_depends),
566 depends=common_depends),
562 Extension('mercurial.osutil', ['mercurial/osutil.c'],
567 Extension('mercurial.osutil', ['mercurial/osutil.c'],
563 extra_link_args=osutil_ldflags,
568 extra_link_args=osutil_ldflags,
564 depends=common_depends),
569 depends=common_depends),
565 Extension('hgext.fsmonitor.pywatchman.bser',
570 Extension('hgext.fsmonitor.pywatchman.bser',
566 ['hgext/fsmonitor/pywatchman/bser.c']),
571 ['hgext/fsmonitor/pywatchman/bser.c']),
567 ]
572 ]
568
573
569 try:
574 try:
570 from distutils import cygwinccompiler
575 from distutils import cygwinccompiler
571
576
572 # the -mno-cygwin option has been deprecated for years
577 # the -mno-cygwin option has been deprecated for years
573 compiler = cygwinccompiler.Mingw32CCompiler
578 compiler = cygwinccompiler.Mingw32CCompiler
574
579
575 class HackedMingw32CCompiler(cygwinccompiler.Mingw32CCompiler):
580 class HackedMingw32CCompiler(cygwinccompiler.Mingw32CCompiler):
576 def __init__(self, *args, **kwargs):
581 def __init__(self, *args, **kwargs):
577 compiler.__init__(self, *args, **kwargs)
582 compiler.__init__(self, *args, **kwargs)
578 for i in 'compiler compiler_so linker_exe linker_so'.split():
583 for i in 'compiler compiler_so linker_exe linker_so'.split():
579 try:
584 try:
580 getattr(self, i).remove('-mno-cygwin')
585 getattr(self, i).remove('-mno-cygwin')
581 except ValueError:
586 except ValueError:
582 pass
587 pass
583
588
584 cygwinccompiler.Mingw32CCompiler = HackedMingw32CCompiler
589 cygwinccompiler.Mingw32CCompiler = HackedMingw32CCompiler
585 except ImportError:
590 except ImportError:
586 # the cygwinccompiler package is not available on some Python
591 # the cygwinccompiler package is not available on some Python
587 # distributions like the ones from the optware project for Synology
592 # distributions like the ones from the optware project for Synology
588 # DiskStation boxes
593 # DiskStation boxes
589 class HackedMingw32CCompiler(object):
594 class HackedMingw32CCompiler(object):
590 pass
595 pass
591
596
592 packagedata = {'mercurial': ['locale/*/LC_MESSAGES/hg.mo',
597 packagedata = {'mercurial': ['locale/*/LC_MESSAGES/hg.mo',
593 'help/*.txt',
598 'help/*.txt',
594 'help/internals/*.txt',
599 'help/internals/*.txt',
595 'default.d/*.rc',
600 'default.d/*.rc',
596 'dummycert.pem']}
601 'dummycert.pem']}
597
602
598 def ordinarypath(p):
603 def ordinarypath(p):
599 return p and p[0] != '.' and p[-1] != '~'
604 return p and p[0] != '.' and p[-1] != '~'
600
605
601 for root in ('templates',):
606 for root in ('templates',):
602 for curdir, dirs, files in os.walk(os.path.join('mercurial', root)):
607 for curdir, dirs, files in os.walk(os.path.join('mercurial', root)):
603 curdir = curdir.split(os.sep, 1)[1]
608 curdir = curdir.split(os.sep, 1)[1]
604 dirs[:] = filter(ordinarypath, dirs)
609 dirs[:] = filter(ordinarypath, dirs)
605 for f in filter(ordinarypath, files):
610 for f in filter(ordinarypath, files):
606 f = os.path.join(curdir, f)
611 f = os.path.join(curdir, f)
607 packagedata['mercurial'].append(f)
612 packagedata['mercurial'].append(f)
608
613
609 datafiles = []
614 datafiles = []
610 setupversion = version
615 setupversion = version
611 extra = {}
616 extra = {}
612
617
613 if py2exeloaded:
618 if py2exeloaded:
614 extra['console'] = [
619 extra['console'] = [
615 {'script':'hg',
620 {'script':'hg',
616 'copyright':'Copyright (C) 2005-2016 Matt Mackall and others',
621 'copyright':'Copyright (C) 2005-2016 Matt Mackall and others',
617 'product_version':version}]
622 'product_version':version}]
618 # sub command of 'build' because 'py2exe' does not handle sub_commands
623 # sub command of 'build' because 'py2exe' does not handle sub_commands
619 build.sub_commands.insert(0, ('build_hgextindex', None))
624 build.sub_commands.insert(0, ('build_hgextindex', None))
620 # put dlls in sub directory so that they won't pollute PATH
625 # put dlls in sub directory so that they won't pollute PATH
621 extra['zipfile'] = 'lib/library.zip'
626 extra['zipfile'] = 'lib/library.zip'
622
627
623 if os.name == 'nt':
628 if os.name == 'nt':
624 # Windows binary file versions for exe/dll files must have the
629 # Windows binary file versions for exe/dll files must have the
625 # form W.X.Y.Z, where W,X,Y,Z are numbers in the range 0..65535
630 # form W.X.Y.Z, where W,X,Y,Z are numbers in the range 0..65535
626 setupversion = version.split('+', 1)[0]
631 setupversion = version.split('+', 1)[0]
627
632
628 if sys.platform == 'darwin' and os.path.exists('/usr/bin/xcodebuild'):
633 if sys.platform == 'darwin' and os.path.exists('/usr/bin/xcodebuild'):
629 version = runcmd(['/usr/bin/xcodebuild', '-version'], {})[0].splitlines()
634 version = runcmd(['/usr/bin/xcodebuild', '-version'], {})[0].splitlines()
630 if version:
635 if version:
631 version = version[0]
636 version = version[0]
632 if sys.version_info[0] == 3:
637 if sys.version_info[0] == 3:
633 version = version.decode('utf-8')
638 version = version.decode('utf-8')
634 xcode4 = (version.startswith('Xcode') and
639 xcode4 = (version.startswith('Xcode') and
635 StrictVersion(version.split()[1]) >= StrictVersion('4.0'))
640 StrictVersion(version.split()[1]) >= StrictVersion('4.0'))
636 xcode51 = re.match(r'^Xcode\s+5\.1', version) is not None
641 xcode51 = re.match(r'^Xcode\s+5\.1', version) is not None
637 else:
642 else:
638 # xcodebuild returns empty on OS X Lion with XCode 4.3 not
643 # xcodebuild returns empty on OS X Lion with XCode 4.3 not
639 # installed, but instead with only command-line tools. Assume
644 # installed, but instead with only command-line tools. Assume
640 # that only happens on >= Lion, thus no PPC support.
645 # that only happens on >= Lion, thus no PPC support.
641 xcode4 = True
646 xcode4 = True
642 xcode51 = False
647 xcode51 = False
643
648
644 # XCode 4.0 dropped support for ppc architecture, which is hardcoded in
649 # XCode 4.0 dropped support for ppc architecture, which is hardcoded in
645 # distutils.sysconfig
650 # distutils.sysconfig
646 if xcode4:
651 if xcode4:
647 os.environ['ARCHFLAGS'] = ''
652 os.environ['ARCHFLAGS'] = ''
648
653
649 # XCode 5.1 changes clang such that it now fails to compile if the
654 # XCode 5.1 changes clang such that it now fails to compile if the
650 # -mno-fused-madd flag is passed, but the version of Python shipped with
655 # -mno-fused-madd flag is passed, but the version of Python shipped with
651 # OS X 10.9 Mavericks includes this flag. This causes problems in all
656 # OS X 10.9 Mavericks includes this flag. This causes problems in all
652 # C extension modules, and a bug has been filed upstream at
657 # C extension modules, and a bug has been filed upstream at
653 # http://bugs.python.org/issue21244. We also need to patch this here
658 # http://bugs.python.org/issue21244. We also need to patch this here
654 # so Mercurial can continue to compile in the meantime.
659 # so Mercurial can continue to compile in the meantime.
655 if xcode51:
660 if xcode51:
656 cflags = get_config_var('CFLAGS')
661 cflags = get_config_var('CFLAGS')
657 if cflags and re.search(r'-mno-fused-madd\b', cflags) is not None:
662 if cflags and re.search(r'-mno-fused-madd\b', cflags) is not None:
658 os.environ['CFLAGS'] = (
663 os.environ['CFLAGS'] = (
659 os.environ.get('CFLAGS', '') + ' -Qunused-arguments')
664 os.environ.get('CFLAGS', '') + ' -Qunused-arguments')
660
665
661 setup(name='mercurial',
666 setup(name='mercurial',
662 version=setupversion,
667 version=setupversion,
663 author='Matt Mackall and many others',
668 author='Matt Mackall and many others',
664 author_email='mercurial@selenic.com',
669 author_email='mercurial@selenic.com',
665 url='https://mercurial-scm.org/',
670 url='https://mercurial-scm.org/',
666 download_url='https://mercurial-scm.org/release/',
671 download_url='https://mercurial-scm.org/release/',
667 description=('Fast scalable distributed SCM (revision control, version '
672 description=('Fast scalable distributed SCM (revision control, version '
668 'control) system'),
673 'control) system'),
669 long_description=('Mercurial is a distributed SCM tool written in Python.'
674 long_description=('Mercurial is a distributed SCM tool written in Python.'
670 ' It is used by a number of large projects that require'
675 ' It is used by a number of large projects that require'
671 ' fast, reliable distributed revision control, such as '
676 ' fast, reliable distributed revision control, such as '
672 'Mozilla.'),
677 'Mozilla.'),
673 license='GNU GPLv2 or any later version',
678 license='GNU GPLv2 or any later version',
674 classifiers=[
679 classifiers=[
675 'Development Status :: 6 - Mature',
680 'Development Status :: 6 - Mature',
676 'Environment :: Console',
681 'Environment :: Console',
677 'Intended Audience :: Developers',
682 'Intended Audience :: Developers',
678 'Intended Audience :: System Administrators',
683 'Intended Audience :: System Administrators',
679 'License :: OSI Approved :: GNU General Public License (GPL)',
684 'License :: OSI Approved :: GNU General Public License (GPL)',
680 'Natural Language :: Danish',
685 'Natural Language :: Danish',
681 'Natural Language :: English',
686 'Natural Language :: English',
682 'Natural Language :: German',
687 'Natural Language :: German',
683 'Natural Language :: Italian',
688 'Natural Language :: Italian',
684 'Natural Language :: Japanese',
689 'Natural Language :: Japanese',
685 'Natural Language :: Portuguese (Brazilian)',
690 'Natural Language :: Portuguese (Brazilian)',
686 'Operating System :: Microsoft :: Windows',
691 'Operating System :: Microsoft :: Windows',
687 'Operating System :: OS Independent',
692 'Operating System :: OS Independent',
688 'Operating System :: POSIX',
693 'Operating System :: POSIX',
689 'Programming Language :: C',
694 'Programming Language :: C',
690 'Programming Language :: Python',
695 'Programming Language :: Python',
691 'Topic :: Software Development :: Version Control',
696 'Topic :: Software Development :: Version Control',
692 ],
697 ],
693 scripts=scripts,
698 scripts=scripts,
694 packages=packages,
699 packages=packages,
695 ext_modules=extmodules,
700 ext_modules=extmodules,
696 data_files=datafiles,
701 data_files=datafiles,
697 package_data=packagedata,
702 package_data=packagedata,
698 cmdclass=cmdclass,
703 cmdclass=cmdclass,
699 distclass=hgdist,
704 distclass=hgdist,
700 options={'py2exe': {'packages': ['hgext', 'email']},
705 options={'py2exe': {'packages': ['hgext', 'email']},
701 'bdist_mpkg': {'zipdist': False,
706 'bdist_mpkg': {'zipdist': False,
702 'license': 'COPYING',
707 'license': 'COPYING',
703 'readme': 'contrib/macosx/Readme.html',
708 'readme': 'contrib/macosx/Readme.html',
704 'welcome': 'contrib/macosx/Welcome.html',
709 'welcome': 'contrib/macosx/Welcome.html',
705 },
710 },
706 },
711 },
707 **extra)
712 **extra)
General Comments 0
You need to be logged in to leave comments. Login now