Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / third_party / cython / src / Tools / cystdlib.py
blob8e16eae78bce10029f11e5f1fabefc300d027e8e
1 """
2 Highly experimental script that compiles the CPython standard library using Cython.
4 Execute the script either in the CPython 'Lib' directory or pass the
5 option '--current-python' to compile the standard library of the running
6 Python interpreter.
8 Pass '-j N' to get a parallel build with N processes.
10 Usage example::
12 $ python cystdlib.py --current-python build_ext -i
13 """
15 import os
16 import sys
17 from distutils.core import setup
18 from Cython.Build import cythonize
19 from Cython.Compiler import Options
21 # improve Python compatibility by allowing some broken code
22 Options.error_on_unknown_names = False
23 Options.error_on_uninitialized = False
25 exclude_patterns = ['**/test/**/*.py', '**/tests/**/*.py', '**/__init__.py']
26 broken = [
27 'idlelib/MultiCall.py',
28 'email/utils.py',
29 'multiprocessing/reduction.py',
30 'multiprocessing/util.py',
31 'threading.py', # interrupt handling
32 'lib2to3/fixes/fix_sys_exc.py',
33 'traceback.py',
34 'types.py',
35 'enum.py',
36 'importlib/_bootstrap',
39 default_directives = dict(
40 auto_cpdef=False, # enable when it's safe, see long list of failures below
41 binding=True,
42 set_initial_path='SOURCEFILE')
43 default_directives['optimize.inline_defnode_calls'] = True
45 special_directives = [
46 (['pkgutil.py',
47 'decimal.py',
48 'datetime.py',
49 'optparse.py',
50 'sndhdr.py',
51 'opcode.py',
52 'ntpath.py',
53 'urllib/request.py',
54 'plat-*/TYPES.py',
55 'plat-*/IN.py',
56 'tkinter/_fix.py',
57 'lib2to3/refactor.py',
58 'webbrowser.py',
59 'shutil.py',
60 'multiprocessing/forking.py',
61 'xml/sax/expatreader.py',
62 'xmlrpc/client.py',
63 'pydoc.py',
64 'xml/etree/ElementTree.py',
65 'posixpath.py',
66 'inspect.py',
67 'ctypes/util.py',
68 'urllib/parse.py',
69 'warnings.py',
70 'tempfile.py',
71 'trace.py',
72 'heapq.py',
73 'pickletools.py',
74 'multiprocessing/connection.py',
75 'hashlib.py',
76 'getopt.py',
77 'os.py',
78 'types.py',
79 ], dict(auto_cpdef=False)),
81 del special_directives[:] # currently unused
83 def build_extensions(includes='**/*.py',
84 excludes=None,
85 special_directives=special_directives,
86 language_level=sys.version_info[0],
87 parallel=None):
88 if isinstance(includes, str):
89 includes = [includes]
90 excludes = list(excludes or exclude_patterns) + broken
92 all_groups = (special_directives or []) + [(includes, {})]
93 extensions = []
94 for modules, directives in all_groups:
95 exclude_now = excludes[:]
96 for other_modules, _ in special_directives:
97 if other_modules != modules:
98 exclude_now.extend(other_modules)
100 d = dict(default_directives)
101 d.update(directives)
103 extensions.extend(
104 cythonize(
105 modules,
106 exclude=exclude_now,
107 exclude_failures=True,
108 language_level=language_level,
109 compiler_directives=d,
110 nthreads=parallel,
112 return extensions
115 def build(extensions):
116 try:
117 setup(ext_modules=extensions)
118 result = True
119 except:
120 import traceback
121 print('error building extensions %s' % (
122 [ext.name for ext in extensions],))
123 traceback.print_exc()
124 result = False
125 return extensions, result
128 def _build(args):
129 sys_args, ext = args
130 sys.argv[1:] = sys_args
131 return build([ext])
134 def parse_args():
135 from optparse import OptionParser
136 parser = OptionParser('%prog [options] [LIB_DIR (default: ./Lib)]')
137 parser.add_option(
138 '--current-python', dest='current_python', action='store_true',
139 help='compile the stdlib of the running Python')
140 parser.add_option(
141 '-j', '--jobs', dest='parallel_jobs', metavar='N',
142 type=int, default=1,
143 help='run builds in N parallel jobs (default: 1)')
144 parser.add_option(
145 '-x', '--exclude', dest='excludes', metavar='PATTERN',
146 action="append", help='exclude modules/packages matching PATTERN')
147 options, args = parser.parse_args()
148 if not args:
149 args = ['./Lib']
150 elif len(args) > 1:
151 parser.error('only one argument expected, got %d' % len(args))
152 return options, args
155 if __name__ == '__main__':
156 options, args = parse_args()
157 if options.current_python:
158 # assume that the stdlib is where the "os" module lives
159 os.chdir(os.path.dirname(os.__file__))
160 else:
161 os.chdir(args[0])
163 pool = None
164 parallel_jobs = options.parallel_jobs
165 if options.parallel_jobs:
166 try:
167 import multiprocessing
168 pool = multiprocessing.Pool(parallel_jobs)
169 print("Building in %d parallel processes" % parallel_jobs)
170 except (ImportError, OSError):
171 print("Not building in parallel")
172 parallel_jobs = 0
174 extensions = build_extensions(
175 parallel=parallel_jobs,
176 excludes=options.excludes)
177 sys_args = ['build_ext', '-i']
178 if pool is not None:
179 results = pool.map(_build, [(sys_args, ext) for ext in extensions])
180 pool.close()
181 pool.join()
182 for ext, result in results:
183 if not result:
184 print("building extension %s failed" % (ext[0].name,))
185 else:
186 sys.argv[1:] = sys_args
187 build(extensions)