##// END OF EJS Templates
exewrapper: adapt for legacy HackableMercurial...
Adrian Buehlmann -
r17732:93d97a21 default
parent child Browse files
Show More
@@ -1,57 +1,58 b''
1 1 syntax: glob
2 2
3 3 *.elc
4 4 *.orig
5 5 *.rej
6 6 *~
7 7 *.mergebackup
8 8 *.o
9 9 *.so
10 10 *.dll
11 11 *.exe
12 12 *.pyd
13 13 *.pyc
14 14 *.pyo
15 15 *$py.class
16 16 *.swp
17 17 *.prof
18 18 *.zip
19 19 \#*\#
20 20 .\#*
21 21 tests/.coverage*
22 22 tests/annotated
23 23 tests/*.err
24 24 tests/htmlcov
25 25 build
26 26 contrib/hgsh/hgsh
27 27 dist
28 28 doc/*.[0-9]
29 29 doc/*.[0-9].gendoc.txt
30 30 doc/*.[0-9].{x,ht}ml
31 31 MANIFEST
32 32 MANIFEST.in
33 33 patches
34 34 mercurial/__version__.py
35 mercurial/hgpythonlib.h
35 36 mercurial.egg-info
36 37 .DS_Store
37 38 tags
38 39 cscope.*
39 40 i18n/hg.pot
40 41 locale/*/LC_MESSAGES/hg.mo
41 42 hgext/__index__.py
42 43
43 44 # files installed with a local --pure build
44 45 mercurial/base85.py
45 46 mercurial/bdiff.py
46 47 mercurial/diffhelpers.py
47 48 mercurial/mpatch.py
48 49 mercurial/osutil.py
49 50 mercurial/parsers.py
50 51
51 52 syntax: regexp
52 53 ^\.pc/
53 54 ^\.(pydev)?project
54 55
55 56 # hackable windows distribution additions
56 57 ^hg-python
57 58 ^hg.py$
@@ -1,101 +1,164 b''
1 1 /*
2 2 exewrapper.c - wrapper for calling a python script on Windows
3 3
4 4 Copyright 2012 Adrian Buehlmann <adrian@cadifra.com> and others
5 5
6 6 This software may be used and distributed according to the terms of the
7 7 GNU General Public License version 2 or any later version.
8 8 */
9 9
10 #include <Python.h>
10 #include <stdio.h>
11 11 #include <windows.h>
12 12
13 #include "hgpythonlib.h"
13 14
14 15 #ifdef __GNUC__
15 16 int strcat_s(char *d, size_t n, const char *s)
16 17 {
17 18 return !strncat(d, s, n);
18 19 }
20 int strcpy_s(char *d, size_t n, const char *s)
21 {
22 return !strncpy(d, s, n);
23 }
19 24 #endif
20 25
21 26
22 27 static char pyscript[MAX_PATH + 10];
28 static char pyhome[MAX_PATH + 10];
29 static char envpyhome[MAX_PATH + 10];
30 static char pydllfile[MAX_PATH + 10];
23 31
24 32 int main(int argc, char *argv[])
25 33 {
26 char *dot;
34 char *p;
27 35 int ret;
28 36 int i;
29 37 int n;
30 38 char **pyargv;
31 39 WIN32_FIND_DATA fdata;
32 40 HANDLE hfind;
33 41 const char *err;
42 HMODULE pydll;
43 void (__cdecl *Py_SetPythonHome)(char *home);
44 int (__cdecl *Py_Main)(int argc, char *argv[]);
34 45
35 46 if (GetModuleFileName(NULL, pyscript, sizeof(pyscript)) == 0)
36 47 {
37 48 err = "GetModuleFileName failed";
38 49 goto bail;
39 50 }
40 51
41 dot = strrchr(pyscript, '.');
42 if (dot == NULL) {
52 p = strrchr(pyscript, '.');
53 if (p == NULL) {
43 54 err = "malformed module filename";
44 55 goto bail;
45 56 }
46 *dot = 0; /* cut trailing ".exe" */
57 *p = 0; /* cut trailing ".exe" */
58 strcpy_s(pyhome, sizeof(pyhome), pyscript);
47 59
48 60 hfind = FindFirstFile(pyscript, &fdata);
49 61 if (hfind != INVALID_HANDLE_VALUE) {
50 62 /* pyscript exists, close handle */
51 63 FindClose(hfind);
52 64 } else {
53 65 /* file pyscript isn't there, take <pyscript>exe.py */
54 66 strcat_s(pyscript, sizeof(pyscript), "exe.py");
55 67 }
56 68
69 pydll = NULL;
70 if (GetEnvironmentVariable("PYTHONHOME", envpyhome,
71 sizeof(envpyhome)) == 0)
72 {
73 /* environment var PYTHONHOME is not set */
74
75 p = strrchr(pyhome, '\\');
76 if (p == NULL) {
77 err = "can't find backslash in module filename";
78 goto bail;
79 }
80 *p = 0; /* cut at directory */
81
82 /* check for private Python of HackableMercurial */
83 strcat_s(pyhome, sizeof(pyhome), "\\hg-python");
84
85 hfind = FindFirstFile(pyhome, &fdata);
86 if (hfind != INVALID_HANDLE_VALUE) {
87 /* path pyhome exists, let's use it */
88 FindClose(hfind);
89 strcpy_s(pydllfile, sizeof(pydllfile), pyhome);
90 strcat_s(pydllfile, sizeof(pydllfile), "\\" HGPYTHONLIB);
91 pydll = LoadLibrary(pydllfile);
92 if (pydll == NULL) {
93 err = "failed to load private Python DLL";
94 goto bail;
95 }
96 Py_SetPythonHome = (void*)GetProcAddress(pydll,
97 "Py_SetPythonHome");
98 if (Py_SetPythonHome == NULL) {
99 err = "failed to get Py_SetPythonHome";
100 goto bail;
101 }
102 Py_SetPythonHome(pyhome);
103 }
104 }
105
106 if (pydll == NULL) {
107 pydll = LoadLibrary(HGPYTHONLIB);
108 if (pydll == NULL) {
109 err = "failed to load Python DLL";
110 goto bail;
111 }
112 }
113
114 Py_Main = (void*)GetProcAddress(pydll, "Py_Main");
115 if (Py_Main == NULL) {
116 err = "failed to get Py_Main";
117 goto bail;
118 }
119
57 120 /*
58 121 Only add the pyscript to the args, if it's not already there. It may
59 122 already be there, if the script spawned a child process of itself, in
60 123 the same way as it got called, that is, with the pyscript already in
61 124 place. So we optionally accept the pyscript as the first argument
62 125 (argv[1]), letting our exe taking the role of the python interpreter.
63 126 */
64 127 if (argc >= 2 && strcmp(argv[1], pyscript) == 0) {
65 128 /*
66 129 pyscript is already in the args, so there is no need to copy
67 130 the args and we can directly call the python interpreter with
68 131 the original args.
69 132 */
70 133 return Py_Main(argc, argv);
71 134 }
72 135
73 136 /*
74 137 Start assembling the args for the Python interpreter call. We put the
75 138 name of our exe (argv[0]) in the position where the python.exe
76 139 canonically is, and insert the pyscript next.
77 140 */
78 141 pyargv = malloc((argc + 5) * sizeof(char*));
79 142 if (pyargv == NULL) {
80 143 err = "not enough memory";
81 144 goto bail;
82 145 }
83 146 n = 0;
84 147 pyargv[n++] = argv[0];
85 148 pyargv[n++] = pyscript;
86 149
87 150 /* copy remaining args from the command line */
88 151 for (i = 1; i < argc; i++)
89 152 pyargv[n++] = argv[i];
90 153 /* argv[argc] is guaranteed to be NULL, so we forward that guarantee */
91 154 pyargv[n] = NULL;
92 155
93 156 ret = Py_Main(n, pyargv); /* The Python interpreter call */
94 157
95 158 free(pyargv);
96 159 return ret;
97 160
98 161 bail:
99 162 fprintf(stderr, "abort: %s\n", err);
100 163 return 255;
101 164 }
@@ -1,534 +1,538 b''
1 1 #
2 2 # This is the mercurial setup script.
3 3 #
4 4 # 'python setup.py install', or
5 5 # 'python setup.py --help' for more options
6 6
7 7 import sys, platform
8 8 if getattr(sys, 'version_info', (0, 0, 0)) < (2, 4, 0, 'final'):
9 9 raise SystemExit("Mercurial requires Python 2.4 or later.")
10 10
11 11 if sys.version_info[0] >= 3:
12 12 def b(s):
13 13 '''A helper function to emulate 2.6+ bytes literals using string
14 14 literals.'''
15 15 return s.encode('latin1')
16 16 else:
17 17 def b(s):
18 18 '''A helper function to emulate 2.6+ bytes literals using string
19 19 literals.'''
20 20 return s
21 21
22 22 # Solaris Python packaging brain damage
23 23 try:
24 24 import hashlib
25 25 sha = hashlib.sha1()
26 26 except ImportError:
27 27 try:
28 28 import sha
29 29 except ImportError:
30 30 raise SystemExit(
31 31 "Couldn't import standard hashlib (incomplete Python install).")
32 32
33 33 try:
34 34 import zlib
35 35 except ImportError:
36 36 raise SystemExit(
37 37 "Couldn't import standard zlib (incomplete Python install).")
38 38
39 39 # The base IronPython distribution (as of 2.7.1) doesn't support bz2
40 40 isironpython = False
41 41 try:
42 42 isironpython = (platform.python_implementation()
43 43 .lower().find("ironpython") != -1)
44 44 except AttributeError:
45 45 pass
46 46
47 47 if isironpython:
48 48 sys.stderr.write("warning: IronPython detected (no bz2 support)\n")
49 49 else:
50 50 try:
51 51 import bz2
52 52 except ImportError:
53 53 raise SystemExit(
54 54 "Couldn't import standard bz2 (incomplete Python install).")
55 55
56 56 import os, subprocess, time
57 57 import shutil
58 58 import tempfile
59 59 from distutils import log
60 60 from distutils.core import setup, Command, Extension
61 61 from distutils.dist import Distribution
62 62 from distutils.command.build import build
63 63 from distutils.command.build_ext import build_ext
64 64 from distutils.command.build_py import build_py
65 65 from distutils.command.install_scripts import install_scripts
66 66 from distutils.spawn import spawn, find_executable
67 67 from distutils.ccompiler import new_compiler
68 68 from distutils import cygwinccompiler
69 69 from distutils.errors import CCompilerError, DistutilsExecError
70 70 from distutils.sysconfig import get_python_inc
71 71 from distutils.version import StrictVersion
72 72
73 73 convert2to3 = '--c2to3' in sys.argv
74 74 if convert2to3:
75 75 try:
76 76 from distutils.command.build_py import build_py_2to3 as build_py
77 77 from lib2to3.refactor import get_fixers_from_package as getfixers
78 78 except ImportError:
79 79 if sys.version_info[0] < 3:
80 80 raise SystemExit("--c2to3 is only compatible with python3.")
81 81 raise
82 82 sys.path.append('contrib')
83 83 elif sys.version_info[0] >= 3:
84 84 raise SystemExit("setup.py with python3 needs --c2to3 (experimental)")
85 85
86 86 scripts = ['hg']
87 87 if os.name == 'nt':
88 88 scripts.append('contrib/win32/hg.bat')
89 89
90 90 # simplified version of distutils.ccompiler.CCompiler.has_function
91 91 # that actually removes its temporary files.
92 92 def hasfunction(cc, funcname):
93 93 tmpdir = tempfile.mkdtemp(prefix='hg-install-')
94 94 devnull = oldstderr = None
95 95 try:
96 96 try:
97 97 fname = os.path.join(tmpdir, 'funcname.c')
98 98 f = open(fname, 'w')
99 99 f.write('int main(void) {\n')
100 100 f.write(' %s();\n' % funcname)
101 101 f.write('}\n')
102 102 f.close()
103 103 # Redirect stderr to /dev/null to hide any error messages
104 104 # from the compiler.
105 105 # This will have to be changed if we ever have to check
106 106 # for a function on Windows.
107 107 devnull = open('/dev/null', 'w')
108 108 oldstderr = os.dup(sys.stderr.fileno())
109 109 os.dup2(devnull.fileno(), sys.stderr.fileno())
110 110 objects = cc.compile([fname], output_dir=tmpdir)
111 111 cc.link_executable(objects, os.path.join(tmpdir, "a.out"))
112 112 except Exception:
113 113 return False
114 114 return True
115 115 finally:
116 116 if oldstderr is not None:
117 117 os.dup2(oldstderr, sys.stderr.fileno())
118 118 if devnull is not None:
119 119 devnull.close()
120 120 shutil.rmtree(tmpdir)
121 121
122 122 # py2exe needs to be installed to work
123 123 try:
124 124 import py2exe
125 125 py2exeloaded = True
126 126 # import py2exe's patched Distribution class
127 127 from distutils.core import Distribution
128 128 except ImportError:
129 129 py2exeloaded = False
130 130
131 131 def runcmd(cmd, env):
132 132 if sys.platform == 'plan9':
133 133 # subprocess kludge to work around issues in half-baked Python
134 134 # ports, notably bichued/python:
135 135 _, out, err = os.popen3(cmd)
136 136 return str(out), str(err)
137 137 else:
138 138 p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
139 139 stderr=subprocess.PIPE, env=env)
140 140 out, err = p.communicate()
141 141 return out, err
142 142
143 143 def runhg(cmd, env):
144 144 out, err = runcmd(cmd, env)
145 145 # If root is executing setup.py, but the repository is owned by
146 146 # another user (as in "sudo python setup.py install") we will get
147 147 # trust warnings since the .hg/hgrc file is untrusted. That is
148 148 # fine, we don't want to load it anyway. Python may warn about
149 149 # a missing __init__.py in mercurial/locale, we also ignore that.
150 150 err = [e for e in err.splitlines()
151 151 if not e.startswith(b('Not trusting file')) \
152 152 and not e.startswith(b('warning: Not importing'))]
153 153 if err:
154 154 return ''
155 155 return out
156 156
157 157 version = ''
158 158
159 159 # Execute hg out of this directory with a custom environment which
160 160 # includes the pure Python modules in mercurial/pure. We also take
161 161 # care to not use any hgrc files and do no localization.
162 162 pypath = ['mercurial', os.path.join('mercurial', 'pure')]
163 163 env = {'PYTHONPATH': os.pathsep.join(pypath),
164 164 'HGRCPATH': '',
165 165 'LANGUAGE': 'C'}
166 166 if 'LD_LIBRARY_PATH' in os.environ:
167 167 env['LD_LIBRARY_PATH'] = os.environ['LD_LIBRARY_PATH']
168 168 if 'SystemRoot' in os.environ:
169 169 # Copy SystemRoot into the custom environment for Python 2.6
170 170 # under Windows. Otherwise, the subprocess will fail with
171 171 # error 0xc0150004. See: http://bugs.python.org/issue3440
172 172 env['SystemRoot'] = os.environ['SystemRoot']
173 173
174 174 if os.path.isdir('.hg'):
175 175 cmd = [sys.executable, 'hg', 'log', '-r', '.', '--template', '{tags}\n']
176 176 numerictags = [t for t in runhg(cmd, env).split() if t[0].isdigit()]
177 177 hgid = runhg([sys.executable, 'hg', 'id', '-i'], env).strip()
178 178 if numerictags: # tag(s) found
179 179 version = numerictags[-1]
180 180 if hgid.endswith('+'): # propagate the dirty status to the tag
181 181 version += '+'
182 182 else: # no tag found
183 183 cmd = [sys.executable, 'hg', 'parents', '--template',
184 184 '{latesttag}+{latesttagdistance}-']
185 185 version = runhg(cmd, env) + hgid
186 186 if version.endswith('+'):
187 187 version += time.strftime('%Y%m%d')
188 188 elif os.path.exists('.hg_archival.txt'):
189 189 kw = dict([[t.strip() for t in l.split(':', 1)]
190 190 for l in open('.hg_archival.txt')])
191 191 if 'tag' in kw:
192 192 version = kw['tag']
193 193 elif 'latesttag' in kw:
194 194 version = '%(latesttag)s+%(latesttagdistance)s-%(node).12s' % kw
195 195 else:
196 196 version = kw.get('node', '')[:12]
197 197
198 198 if version:
199 199 f = open("mercurial/__version__.py", "w")
200 200 f.write('# this file is autogenerated by setup.py\n')
201 201 f.write('version = "%s"\n' % version)
202 202 f.close()
203 203
204 204
205 205 try:
206 206 from mercurial import __version__
207 207 version = __version__.version
208 208 except ImportError:
209 209 version = 'unknown'
210 210
211 211 class hgbuild(build):
212 212 # Insert hgbuildmo first so that files in mercurial/locale/ are found
213 213 # when build_py is run next.
214 214 sub_commands = [('build_mo', None),
215 215
216 216 # We also need build_ext before build_py. Otherwise, when 2to3 is
217 217 # called (in build_py), it will not find osutil & friends,
218 218 # thinking that those modules are global and, consequently, making
219 219 # a mess, now that all module imports are global.
220 220
221 221 ('build_ext', build.has_ext_modules),
222 222 ] + build.sub_commands
223 223
224 224 class hgbuildmo(build):
225 225
226 226 description = "build translations (.mo files)"
227 227
228 228 def run(self):
229 229 if not find_executable('msgfmt'):
230 230 self.warn("could not find msgfmt executable, no translations "
231 231 "will be built")
232 232 return
233 233
234 234 podir = 'i18n'
235 235 if not os.path.isdir(podir):
236 236 self.warn("could not find %s/ directory" % podir)
237 237 return
238 238
239 239 join = os.path.join
240 240 for po in os.listdir(podir):
241 241 if not po.endswith('.po'):
242 242 continue
243 243 pofile = join(podir, po)
244 244 modir = join('locale', po[:-3], 'LC_MESSAGES')
245 245 mofile = join(modir, 'hg.mo')
246 246 mobuildfile = join('mercurial', mofile)
247 247 cmd = ['msgfmt', '-v', '-o', mobuildfile, pofile]
248 248 if sys.platform != 'sunos5':
249 249 # msgfmt on Solaris does not know about -c
250 250 cmd.append('-c')
251 251 self.mkpath(join('mercurial', modir))
252 252 self.make_file([pofile], mobuildfile, spawn, (cmd,))
253 253
254 254
255 255 class hgdist(Distribution):
256 256 pure = 0
257 257
258 258 global_options = Distribution.global_options + \
259 259 [('pure', None, "use pure (slow) Python "
260 260 "code instead of C extensions"),
261 261 ('c2to3', None, "(experimental!) convert "
262 262 "code with 2to3"),
263 263 ]
264 264
265 265 def has_ext_modules(self):
266 266 # self.ext_modules is emptied in hgbuildpy.finalize_options which is
267 267 # too late for some cases
268 268 return not self.pure and Distribution.has_ext_modules(self)
269 269
270 270 class hgbuildext(build_ext):
271 271
272 272 def build_extension(self, ext):
273 273 try:
274 274 build_ext.build_extension(self, ext)
275 275 except CCompilerError:
276 276 if not getattr(ext, 'optional', False):
277 277 raise
278 278 log.warn("Failed to build optional extension '%s' (skipping)",
279 279 ext.name)
280 280
281 281 class hgbuildpy(build_py):
282 282 if convert2to3:
283 283 fixer_names = sorted(set(getfixers("lib2to3.fixes") +
284 284 getfixers("hgfixes")))
285 285
286 286 def finalize_options(self):
287 287 build_py.finalize_options(self)
288 288
289 289 if self.distribution.pure:
290 290 if self.py_modules is None:
291 291 self.py_modules = []
292 292 for ext in self.distribution.ext_modules:
293 293 if ext.name.startswith("mercurial."):
294 294 self.py_modules.append("mercurial.pure.%s" % ext.name[10:])
295 295 self.distribution.ext_modules = []
296 296 else:
297 297 if not os.path.exists(os.path.join(get_python_inc(), 'Python.h')):
298 298 raise SystemExit('Python headers are required to build '
299 299 'Mercurial')
300 300
301 301 def find_modules(self):
302 302 modules = build_py.find_modules(self)
303 303 for module in modules:
304 304 if module[0] == "mercurial.pure":
305 305 if module[1] != "__init__":
306 306 yield ("mercurial", module[1], module[2])
307 307 else:
308 308 yield module
309 309
310 310 class buildhgextindex(Command):
311 311 description = 'generate prebuilt index of hgext (for frozen package)'
312 312 user_options = []
313 313 _indexfilename = 'hgext/__index__.py'
314 314
315 315 def initialize_options(self):
316 316 pass
317 317
318 318 def finalize_options(self):
319 319 pass
320 320
321 321 def run(self):
322 322 if os.path.exists(self._indexfilename):
323 323 os.unlink(self._indexfilename)
324 324
325 325 # here no extension enabled, disabled() lists up everything
326 326 code = ('import pprint; from mercurial import extensions; '
327 327 'pprint.pprint(extensions.disabled())')
328 328 out, err = runcmd([sys.executable, '-c', code], env)
329 329 if err:
330 330 raise DistutilsExecError(err)
331 331
332 332 f = open(self._indexfilename, 'w')
333 333 f.write('# this file is autogenerated by setup.py\n')
334 334 f.write('docs = ')
335 335 f.write(out)
336 336 f.close()
337 337
338 338 class buildhgexe(build_ext):
339 339 description = 'compile hg.exe from mercurial/exewrapper.c'
340 340
341 341 def build_extensions(self):
342 342 if os.name != 'nt':
343 343 return
344 344 if isinstance(self.compiler, HackedMingw32CCompiler):
345 345 self.compiler.compiler_so = self.compiler.compiler # no -mdll
346 346 self.compiler.dll_libraries = [] # no -lmsrvc90
347 hv = sys.hexversion
348 pythonlib = 'python%d%d' % (hv >> 24, (hv >> 16) & 0xff)
349 f = open('mercurial/hgpythonlib.h', 'wb')
350 f.write('/* this file is autogenerated by setup.py */\n')
351 f.write('#define HGPYTHONLIB "%s"\n' % pythonlib)
352 f.close()
347 353 objects = self.compiler.compile(['mercurial/exewrapper.c'],
348 354 output_dir=self.build_temp)
349 355 dir = os.path.dirname(self.get_ext_fullpath('dummy'))
350 356 target = os.path.join(dir, 'hg')
351 pythonlib = ("python%d%d" %
352 (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff))
353 357 self.compiler.link_executable(objects, target,
354 libraries=[pythonlib],
358 libraries=[],
355 359 output_dir=self.build_temp)
356 360
357 361 class hginstallscripts(install_scripts):
358 362 '''
359 363 This is a specialization of install_scripts that replaces the @LIBDIR@ with
360 364 the configured directory for modules. If possible, the path is made relative
361 365 to the directory for scripts.
362 366 '''
363 367
364 368 def initialize_options(self):
365 369 install_scripts.initialize_options(self)
366 370
367 371 self.install_lib = None
368 372
369 373 def finalize_options(self):
370 374 install_scripts.finalize_options(self)
371 375 self.set_undefined_options('install',
372 376 ('install_lib', 'install_lib'))
373 377
374 378 def run(self):
375 379 install_scripts.run(self)
376 380
377 381 if (os.path.splitdrive(self.install_dir)[0] !=
378 382 os.path.splitdrive(self.install_lib)[0]):
379 383 # can't make relative paths from one drive to another, so use an
380 384 # absolute path instead
381 385 libdir = self.install_lib
382 386 else:
383 387 common = os.path.commonprefix((self.install_dir, self.install_lib))
384 388 rest = self.install_dir[len(common):]
385 389 uplevel = len([n for n in os.path.split(rest) if n])
386 390
387 391 libdir = uplevel * ('..' + os.sep) + self.install_lib[len(common):]
388 392
389 393 for outfile in self.outfiles:
390 394 fp = open(outfile, 'rb')
391 395 data = fp.read()
392 396 fp.close()
393 397
394 398 # skip binary files
395 399 if b('\0') in data:
396 400 continue
397 401
398 402 data = data.replace('@LIBDIR@', libdir.encode('string_escape'))
399 403 fp = open(outfile, 'wb')
400 404 fp.write(data)
401 405 fp.close()
402 406
403 407 cmdclass = {'build': hgbuild,
404 408 'build_mo': hgbuildmo,
405 409 'build_ext': hgbuildext,
406 410 'build_py': hgbuildpy,
407 411 'build_hgextindex': buildhgextindex,
408 412 'install_scripts': hginstallscripts,
409 413 'build_hgexe': buildhgexe,
410 414 }
411 415
412 416 packages = ['mercurial', 'mercurial.hgweb', 'mercurial.httpclient',
413 417 'hgext', 'hgext.convert', 'hgext.highlight', 'hgext.zeroconf',
414 418 'hgext.largefiles']
415 419
416 420 pymodules = []
417 421
418 422 extmodules = [
419 423 Extension('mercurial.base85', ['mercurial/base85.c']),
420 424 Extension('mercurial.bdiff', ['mercurial/bdiff.c']),
421 425 Extension('mercurial.diffhelpers', ['mercurial/diffhelpers.c']),
422 426 Extension('mercurial.mpatch', ['mercurial/mpatch.c']),
423 427 Extension('mercurial.parsers', ['mercurial/parsers.c',
424 428 'mercurial/pathencode.c']),
425 429 ]
426 430
427 431 osutil_ldflags = []
428 432
429 433 if sys.platform == 'darwin':
430 434 osutil_ldflags += ['-framework', 'ApplicationServices']
431 435
432 436 # disable osutil.c under windows + python 2.4 (issue1364)
433 437 if sys.platform == 'win32' and sys.version_info < (2, 5, 0, 'final'):
434 438 pymodules.append('mercurial.pure.osutil')
435 439 else:
436 440 extmodules.append(Extension('mercurial.osutil', ['mercurial/osutil.c'],
437 441 extra_link_args=osutil_ldflags))
438 442
439 443 # the -mno-cygwin option has been deprecated for years
440 444 Mingw32CCompiler = cygwinccompiler.Mingw32CCompiler
441 445
442 446 class HackedMingw32CCompiler(cygwinccompiler.Mingw32CCompiler):
443 447 def __init__(self, *args, **kwargs):
444 448 Mingw32CCompiler.__init__(self, *args, **kwargs)
445 449 for i in 'compiler compiler_so linker_exe linker_so'.split():
446 450 try:
447 451 getattr(self, i).remove('-mno-cygwin')
448 452 except ValueError:
449 453 pass
450 454
451 455 cygwinccompiler.Mingw32CCompiler = HackedMingw32CCompiler
452 456
453 457 if sys.platform.startswith('linux') and os.uname()[2] > '2.6':
454 458 # The inotify extension is only usable with Linux 2.6 kernels.
455 459 # You also need a reasonably recent C library.
456 460 # In any case, if it fails to build the error will be skipped ('optional').
457 461 cc = new_compiler()
458 462 if hasfunction(cc, 'inotify_add_watch'):
459 463 inotify = Extension('hgext.inotify.linux._inotify',
460 464 ['hgext/inotify/linux/_inotify.c'],
461 465 ['mercurial'])
462 466 inotify.optional = True
463 467 extmodules.append(inotify)
464 468 packages.extend(['hgext.inotify', 'hgext.inotify.linux'])
465 469
466 470 packagedata = {'mercurial': ['locale/*/LC_MESSAGES/hg.mo',
467 471 'help/*.txt']}
468 472
469 473 def ordinarypath(p):
470 474 return p and p[0] != '.' and p[-1] != '~'
471 475
472 476 for root in ('templates',):
473 477 for curdir, dirs, files in os.walk(os.path.join('mercurial', root)):
474 478 curdir = curdir.split(os.sep, 1)[1]
475 479 dirs[:] = filter(ordinarypath, dirs)
476 480 for f in filter(ordinarypath, files):
477 481 f = os.path.join(curdir, f)
478 482 packagedata['mercurial'].append(f)
479 483
480 484 datafiles = []
481 485 setupversion = version
482 486 extra = {}
483 487
484 488 if py2exeloaded:
485 489 extra['console'] = [
486 490 {'script':'hg',
487 491 'copyright':'Copyright (C) 2005-2010 Matt Mackall and others',
488 492 'product_version':version}]
489 493 # sub command of 'build' because 'py2exe' does not handle sub_commands
490 494 build.sub_commands.insert(0, ('build_hgextindex', None))
491 495
492 496 if os.name == 'nt':
493 497 # Windows binary file versions for exe/dll files must have the
494 498 # form W.X.Y.Z, where W,X,Y,Z are numbers in the range 0..65535
495 499 setupversion = version.split('+', 1)[0]
496 500
497 501 if sys.platform == 'darwin' and os.path.exists('/usr/bin/xcodebuild'):
498 502 # XCode 4.0 dropped support for ppc architecture, which is hardcoded in
499 503 # distutils.sysconfig
500 504 version = runcmd(['/usr/bin/xcodebuild', '-version'], {})[0].splitlines()
501 505 if version:
502 506 version = version[0]
503 507 xcode4 = (version.startswith('Xcode') and
504 508 StrictVersion(version.split()[1]) >= StrictVersion('4.0'))
505 509 else:
506 510 # xcodebuild returns empty on OS X Lion with XCode 4.3 not
507 511 # installed, but instead with only command-line tools. Assume
508 512 # that only happens on >= Lion, thus no PPC support.
509 513 xcode4 = True
510 514
511 515 if xcode4:
512 516 os.environ['ARCHFLAGS'] = ''
513 517
514 518 setup(name='mercurial',
515 519 version=setupversion,
516 520 author='Matt Mackall',
517 521 author_email='mpm@selenic.com',
518 522 url='http://mercurial.selenic.com/',
519 523 description='Scalable distributed SCM',
520 524 license='GNU GPLv2+',
521 525 scripts=scripts,
522 526 packages=packages,
523 527 py_modules=pymodules,
524 528 ext_modules=extmodules,
525 529 data_files=datafiles,
526 530 package_data=packagedata,
527 531 cmdclass=cmdclass,
528 532 distclass=hgdist,
529 533 options=dict(py2exe=dict(packages=['hgext', 'email']),
530 534 bdist_mpkg=dict(zipdist=True,
531 535 license='COPYING',
532 536 readme='contrib/macosx/Readme.html',
533 537 welcome='contrib/macosx/Welcome.html')),
534 538 **extra)
General Comments 0
You need to be logged in to leave comments. Login now