1 # Copyright 2018 The gRPC Authors
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 """Patches the compile() to allow enable parallel compilation of C/C++.
16 build_ext has lots of C/C++ files and normally them one by one.
17 Enabling parallel build helps a lot.
20 import distutils.ccompiler
24 BUILD_EXT_COMPILER_JOBS = int(
25 os.environ.get('GRPC_PYTHON_BUILD_EXT_COMPILER_JOBS', '1'))
27 BUILD_EXT_COMPILER_JOBS = 1
30 # monkey-patch for parallel compilation
31 def _parallel_compile(self,
40 # setup the same way as distutils.ccompiler.CCompiler
41 # https://github.com/python/cpython/blob/31368a4f0e531c19affe2a1becd25fc316bc7501/Lib/distutils/ccompiler.py#L564
42 macros, objects, extra_postargs, pp_opts, build = self._setup_compile(
43 str(output_dir), macros, include_dirs, sources, depends, extra_postargs)
44 cc_args = self._get_cc_args(pp_opts, debug, extra_preargs)
46 def _compile_single_file(obj):
51 self._compile(obj, src, ext, cc_args, extra_postargs, pp_opts)
53 # run compilation of individual files in parallel
54 import multiprocessing.pool
55 multiprocessing.pool.ThreadPool(BUILD_EXT_COMPILER_JOBS).map(
56 _compile_single_file, objects)
60 def monkeypatch_compile_maybe():
61 """Monkeypatching is dumb, but the build speed gain is worth it."""
62 if BUILD_EXT_COMPILER_JOBS > 1:
63 distutils.ccompiler.CCompiler.compile = _parallel_compile