Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / third_party / cython / src / Cython / Build / Cythonize.py
blobb36fa60fdbb1a0543f5baf704d77b26ad0dcc97e
1 #!/usr/bin/env python
3 import os
4 import shutil
5 import tempfile
7 from distutils.core import setup
8 from Cython.Build.Dependencies import cythonize, extended_iglob
9 from Cython.Utils import is_package_dir
10 from Cython.Compiler import Options
12 try:
13 import multiprocessing
14 parallel_compiles = int(multiprocessing.cpu_count() * 1.5)
15 except ImportError:
16 multiprocessing = None
17 parallel_compiles = 0
20 class _FakePool(object):
21 def map_async(self, func, args):
22 from itertools import imap
23 for _ in imap(func, args):
24 pass
26 def close(self): pass
27 def terminate(self): pass
28 def join(self): pass
31 def parse_directives(option, name, value, parser):
32 dest = option.dest
33 old_directives = dict(getattr(parser.values, dest,
34 Options.directive_defaults))
35 directives = Options.parse_directive_list(
36 value, relaxed_bool=True, current_settings=old_directives)
37 setattr(parser.values, dest, directives)
40 def parse_options(option, name, value, parser):
41 dest = option.dest
42 options = dict(getattr(parser.values, dest, {}))
43 for opt in value.split(','):
44 if '=' in opt:
45 n, v = opt.split('=', 1)
46 v = v.lower() not in ('false', 'f', '0', 'no')
47 else:
48 n, v = opt, True
49 options[n] = v
50 setattr(parser.values, dest, options)
53 def find_package_base(path):
54 base_dir, package_path = os.path.split(path)
55 while os.path.isfile(os.path.join(base_dir, '__init__.py')):
56 base_dir, parent = os.path.split(base_dir)
57 package_path = '%s/%s' % (parent, package_path)
58 return base_dir, package_path
61 def cython_compile(path_pattern, options):
62 pool = None
63 paths = map(os.path.abspath, extended_iglob(path_pattern))
64 try:
65 for path in paths:
66 if options.build_inplace:
67 base_dir = path
68 while not os.path.isdir(base_dir) or is_package_dir(base_dir):
69 base_dir = os.path.dirname(base_dir)
70 else:
71 base_dir = None
73 if os.path.isdir(path):
74 # recursively compiling a package
75 paths = [os.path.join(path, '**', '*.%s' % ext)
76 for ext in ('py', 'pyx')]
77 else:
78 # assume it's a file(-like thing)
79 paths = [path]
81 ext_modules = cythonize(
82 paths,
83 nthreads=options.parallel,
84 exclude_failures=options.keep_going,
85 exclude=options.excludes,
86 compiler_directives=options.directives,
87 force=options.force,
88 quiet=options.quiet,
89 **options.options)
91 if ext_modules and options.build:
92 if len(ext_modules) > 1 and options.parallel > 1:
93 if pool is None:
94 try:
95 pool = multiprocessing.Pool(options.parallel)
96 except OSError:
97 pool = _FakePool()
98 pool.map_async(run_distutils, [
99 (base_dir, [ext]) for ext in ext_modules])
100 else:
101 run_distutils((base_dir, ext_modules))
102 except:
103 if pool is not None:
104 pool.terminate()
105 raise
106 else:
107 if pool is not None:
108 pool.close()
109 pool.join()
112 def run_distutils(args):
113 base_dir, ext_modules = args
114 script_args = ['build_ext', '-i']
115 cwd = os.getcwd()
116 temp_dir = None
117 try:
118 if base_dir:
119 os.chdir(base_dir)
120 temp_dir = tempfile.mkdtemp(dir=base_dir)
121 script_args.extend(['--build-temp', temp_dir])
122 setup(
123 script_name='setup.py',
124 script_args=script_args,
125 ext_modules=ext_modules,
127 finally:
128 if base_dir:
129 os.chdir(cwd)
130 if temp_dir and os.path.isdir(temp_dir):
131 shutil.rmtree(temp_dir)
134 def parse_args(args):
135 from optparse import OptionParser
136 parser = OptionParser(usage='%prog [options] [sources and packages]+')
138 parser.add_option('-X', '--directive', metavar='NAME=VALUE,...', dest='directives',
139 type=str, action='callback', callback=parse_directives, default={},
140 help='set a compiler directive')
141 parser.add_option('-s', '--option', metavar='NAME=VALUE', dest='options',
142 type=str, action='callback', callback=parse_options, default={},
143 help='set a cythonize option')
144 parser.add_option('-3', dest='python3_mode', action='store_true',
145 help='use Python 3 syntax mode by default')
147 parser.add_option('-x', '--exclude', metavar='PATTERN', dest='excludes',
148 action='append', default=[],
149 help='exclude certain file patterns from the compilation')
151 parser.add_option('-b', '--build', dest='build', action='store_true',
152 help='build extension modules using distutils')
153 parser.add_option('-i', '--inplace', dest='build_inplace', action='store_true',
154 help='build extension modules in place using distutils (implies -b)')
155 parser.add_option('-j', '--parallel', dest='parallel', metavar='N',
156 type=int, default=parallel_compiles,
157 help=('run builds in N parallel jobs (default: %d)' %
158 parallel_compiles or 1))
159 parser.add_option('-f', '--force', dest='force', action='store_true',
160 help='force recompilation')
161 parser.add_option('-q', '--quiet', dest='quiet', action='store_true',
162 help='be less verbose during compilation')
164 parser.add_option('--lenient', dest='lenient', action='store_true',
165 help='increase Python compatibility by ignoring some compile time errors')
166 parser.add_option('-k', '--keep-going', dest='keep_going', action='store_true',
167 help='compile as much as possible, ignore compilation failures')
169 options, args = parser.parse_args(args)
170 if not args:
171 parser.error("no source files provided")
172 if options.build_inplace:
173 options.build = True
174 if multiprocessing is None:
175 options.parallel = 0
176 if options.python3_mode:
177 options.options['language_level'] = 3
178 return options, args
181 def main(args=None):
182 options, paths = parse_args(args)
184 if options.lenient:
185 # increase Python compatibility by ignoring compile time errors
186 Options.error_on_unknown_names = False
187 Options.error_on_uninitialized = False
189 for path in paths:
190 cython_compile(path, options)
193 if __name__ == '__main__':
194 main()