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