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