|
22 | 22 | import setuptools |
23 | 23 | from setuptools.command.easy_install import easy_install |
24 | 24 | from setuptools.command.build_ext import build_ext |
| 25 | +from distutils.command.build import build |
25 | 26 |
|
26 | 27 | from .extension_utils import find_cuda_home, normalize_extension_kwargs, add_compile_flag, bootstrap_context |
27 | 28 | from .extension_utils import is_cuda_file, prepare_unix_cudaflags, prepare_win_cudaflags, add_std_without_repeat, get_build_directory |
@@ -103,6 +104,13 @@ def setup(**attr): |
103 | 104 | assert 'easy_install' not in cmdclass |
104 | 105 | cmdclass['easy_install'] = EasyInstallCommand |
105 | 106 |
|
| 107 | + # Note(Aurelius84): Add rename build_base directory hook in build command. |
| 108 | + # To avoid using same build directory that will lead to remove the directory |
| 109 | + # by mistake while parallelling execute setup.py, for example on CI. |
| 110 | + assert 'build' not in cmdclass |
| 111 | + build_base = os.path.join('build', attr['name']) |
| 112 | + cmdclass['build'] = BuildCommand.with_options(build_base=build_base) |
| 113 | + |
106 | 114 | # Always set zip_safe=False to make compatible in PY2 and PY3 |
107 | 115 | # See http://peak.telecommunity.com/DevCenter/setuptools#setting-the-zip-safe-flag |
108 | 116 | attr['zip_safe'] = False |
@@ -491,6 +499,43 @@ def run(self, *args, **kwargs): |
491 | 499 | assert os.path.exists(new_so_path) |
492 | 500 |
|
493 | 501 |
|
| 502 | +class BuildCommand(build, object): |
| 503 | + """ |
| 504 | + Extend build Command to control the behavior of specifying `build_base` root directory. |
| 505 | +
|
| 506 | + NOTE(Aurelius84): This is a hook subclass inherited Command used to specify customized |
| 507 | + build_base directory. |
| 508 | + """ |
| 509 | + |
| 510 | + @classmethod |
| 511 | + def with_options(cls, **options): |
| 512 | + """ |
| 513 | + Returns a BuildCommand subclass containing use-defined options. |
| 514 | + """ |
| 515 | + |
| 516 | + class cls_with_options(cls): |
| 517 | + def __init__(self, *args, **kwargs): |
| 518 | + kwargs.update(options) |
| 519 | + cls.__init__(self, *args, **kwargs) |
| 520 | + |
| 521 | + return cls_with_options |
| 522 | + |
| 523 | + def __init__(self, *args, **kwargs): |
| 524 | + # Note: shall put before super() |
| 525 | + self._specified_build_base = kwargs.get('build_base', None) |
| 526 | + |
| 527 | + super(BuildCommand, self).__init__(*args, **kwargs) |
| 528 | + |
| 529 | + def initialize_options(self): |
| 530 | + """ |
| 531 | + build_base is root directory for all sub-command, such as |
| 532 | + build_lib, build_temp. See `distutils.command.build` for details. |
| 533 | + """ |
| 534 | + super(BuildCommand, self).initialize_options() |
| 535 | + if self._specified_build_base is not None: |
| 536 | + self.build_base = self._specified_build_base |
| 537 | + |
| 538 | + |
494 | 539 | def load(name, |
495 | 540 | sources, |
496 | 541 | extra_cflags=None, |
@@ -569,11 +614,13 @@ def load(name, |
569 | 614 | verbose) |
570 | 615 |
|
571 | 616 | # write setup.py file and compile it |
572 | | - _write_setup_file(name, sources, file_path, extra_include_paths, |
573 | | - compile_flags, extra_ldflags, verbose) |
| 617 | + build_base_dir = os.path.join(build_directory, name) |
| 618 | + _write_setup_file(name, sources, file_path, build_base_dir, |
| 619 | + extra_include_paths, compile_flags, extra_ldflags, |
| 620 | + verbose) |
574 | 621 | _jit_compile(file_path, interpreter, verbose) |
575 | 622 |
|
576 | 623 | # import as callable python api |
577 | | - custom_op_api = _import_module_from_library(name, build_directory, verbose) |
| 624 | + custom_op_api = _import_module_from_library(name, build_base_dir, verbose) |
578 | 625 |
|
579 | 626 | return custom_op_api |
0 commit comments