| | import glob |
| | import os |
| | import platform |
| | import re |
| | from pkg_resources import DistributionNotFound, get_distribution, parse_version |
| | from setuptools import find_packages, setup |
| |
|
| | EXT_TYPE = '' |
| | try: |
| | import torch |
| | if torch.__version__ == 'parrots': |
| | from parrots.utils.build_extension import BuildExtension |
| | EXT_TYPE = 'parrots' |
| | elif (hasattr(torch, 'is_mlu_available') and torch.is_mlu_available()) or \ |
| | os.getenv('FORCE_MLU', '0') == '1': |
| | from torch_mlu.utils.cpp_extension import BuildExtension |
| | EXT_TYPE = 'pytorch' |
| | else: |
| | from torch.utils.cpp_extension import BuildExtension |
| | EXT_TYPE = 'pytorch' |
| | cmd_class = {'build_ext': BuildExtension} |
| | except ModuleNotFoundError: |
| | cmd_class = {} |
| | print('Skip building ext ops due to the absence of torch.') |
| |
|
| |
|
| | def choose_requirement(primary, secondary): |
| | """If some version of primary requirement installed, return primary, else |
| | return secondary.""" |
| | try: |
| | name = re.split(r'[!<>=]', primary)[0] |
| | get_distribution(name) |
| | except DistributionNotFound: |
| | return secondary |
| |
|
| | return str(primary) |
| |
|
| |
|
| | def get_version(): |
| | version_file = 'mmcv/version.py' |
| | with open(version_file, encoding='utf-8') as f: |
| | exec(compile(f.read(), version_file, 'exec')) |
| | return locals()['__version__'] |
| |
|
| |
|
| | def parse_requirements(fname='requirements/runtime.txt', with_version=True): |
| | """Parse the package dependencies listed in a requirements file but strips |
| | specific versioning information. |
| | |
| | Args: |
| | fname (str): path to requirements file |
| | with_version (bool, default=False): if True include version specs |
| | |
| | Returns: |
| | List[str]: list of requirements items |
| | |
| | CommandLine: |
| | python -c "import setup; print(setup.parse_requirements())" |
| | """ |
| | import sys |
| | from os.path import exists |
| | require_fpath = fname |
| |
|
| | def parse_line(line): |
| | """Parse information from a line in a requirements text file.""" |
| | if line.startswith('-r '): |
| | |
| | target = line.split(' ')[1] |
| | for info in parse_require_file(target): |
| | yield info |
| | else: |
| | info = {'line': line} |
| | if line.startswith('-e '): |
| | info['package'] = line.split('#egg=')[1] |
| | else: |
| | |
| | pat = '(' + '|'.join(['>=', '==', '>']) + ')' |
| | parts = re.split(pat, line, maxsplit=1) |
| | parts = [p.strip() for p in parts] |
| |
|
| | info['package'] = parts[0] |
| | if len(parts) > 1: |
| | op, rest = parts[1:] |
| | if ';' in rest: |
| | |
| | |
| | version, platform_deps = map(str.strip, |
| | rest.split(';')) |
| | info['platform_deps'] = platform_deps |
| | else: |
| | version = rest |
| | info['version'] = (op, version) |
| | yield info |
| |
|
| | def parse_require_file(fpath): |
| | with open(fpath) as f: |
| | for line in f.readlines(): |
| | line = line.strip() |
| | if line and not line.startswith('#'): |
| | yield from parse_line(line) |
| |
|
| | def gen_packages_items(): |
| | if exists(require_fpath): |
| | for info in parse_require_file(require_fpath): |
| | parts = [info['package']] |
| | if with_version and 'version' in info: |
| | parts.extend(info['version']) |
| | if not sys.version.startswith('3.4'): |
| | |
| | platform_deps = info.get('platform_deps') |
| | if platform_deps is not None: |
| | parts.append(';' + platform_deps) |
| | item = ''.join(parts) |
| | yield item |
| |
|
| | packages = list(gen_packages_items()) |
| | return packages |
| |
|
| |
|
| | install_requires = parse_requirements() |
| |
|
| | try: |
| | |
| | import cv2 |
| | major, minor, *rest = cv2.__version__.split('.') |
| | if int(major) < 3: |
| | raise RuntimeError( |
| | f'OpenCV >=3 is required but {cv2.__version__} is installed') |
| | except ImportError: |
| | |
| | CHOOSE_INSTALL_REQUIRES = [('opencv-python-headless>=3', |
| | 'opencv-python>=3')] |
| | for main, secondary in CHOOSE_INSTALL_REQUIRES: |
| | install_requires.append(choose_requirement(main, secondary)) |
| |
|
| |
|
| | def get_extensions(): |
| | extensions = [] |
| |
|
| | if os.getenv('MMCV_WITH_OPS', '1') == '0': |
| | return extensions |
| |
|
| | if EXT_TYPE == 'parrots': |
| | ext_name = 'mmcv._ext' |
| | from parrots.utils.build_extension import Extension |
| |
|
| | |
| | |
| | define_macros = [] |
| | include_dirs = [] |
| | op_files = glob.glob('./mmcv/ops/csrc/pytorch/cuda/*.cu') +\ |
| | glob.glob('./mmcv/ops/csrc/pytorch/cpu/*.cpp') +\ |
| | glob.glob('./mmcv/ops/csrc/parrots/*.cpp') |
| | include_dirs.append(os.path.abspath('./mmcv/ops/csrc/common')) |
| | include_dirs.append(os.path.abspath('./mmcv/ops/csrc/common/cuda')) |
| | op_files.remove('./mmcv/ops/csrc/pytorch/cuda/iou3d_cuda.cu') |
| | op_files.remove('./mmcv/ops/csrc/pytorch/cpu/bbox_overlaps_cpu.cpp') |
| | op_files.remove('./mmcv/ops/csrc/pytorch/cuda/bias_act_cuda.cu') |
| | cuda_args = os.getenv('MMCV_CUDA_ARGS') |
| | extra_compile_args = { |
| | 'nvcc': [cuda_args, '-std=c++14'] if cuda_args else ['-std=c++14'], |
| | 'cxx': ['-std=c++14'], |
| | } |
| | if torch.cuda.is_available() or os.getenv('FORCE_CUDA', '0') == '1': |
| | define_macros += [('MMCV_WITH_CUDA', None)] |
| | extra_compile_args['nvcc'] += [ |
| | '-D__CUDA_NO_HALF_OPERATORS__', |
| | '-D__CUDA_NO_HALF_CONVERSIONS__', |
| | '-D__CUDA_NO_HALF2_OPERATORS__', |
| | ] |
| | ext_ops = Extension( |
| | name=ext_name, |
| | sources=op_files, |
| | include_dirs=include_dirs, |
| | define_macros=define_macros, |
| | extra_compile_args=extra_compile_args, |
| | cuda=True, |
| | pytorch=True) |
| | extensions.append(ext_ops) |
| | elif EXT_TYPE == 'pytorch': |
| | ext_name = 'mmcv._ext' |
| | from torch.utils.cpp_extension import CppExtension, CUDAExtension |
| |
|
| | |
| | try: |
| | import psutil |
| | num_cpu = len(psutil.Process().cpu_affinity()) |
| | cpu_use = max(4, num_cpu - 1) |
| | except (ModuleNotFoundError, AttributeError): |
| | cpu_use = 4 |
| |
|
| | os.environ.setdefault('MAX_JOBS', str(cpu_use)) |
| | define_macros = [] |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | extra_compile_args = {'cxx': []} |
| |
|
| | if platform.system() != 'Windows': |
| | if parse_version(torch.__version__) <= parse_version('1.12.1'): |
| | extra_compile_args['cxx'] = ['-std=c++14'] |
| | else: |
| | extra_compile_args['cxx'] = ['-std=c++17'] |
| | else: |
| | if parse_version(torch.__version__) <= parse_version('1.12.1'): |
| | extra_compile_args['cxx'] = ['/std:c++14'] |
| | else: |
| | extra_compile_args['cxx'] = ['/std:c++17'] |
| |
|
| | include_dirs = [] |
| | library_dirs = [] |
| | libraries = [] |
| |
|
| | extra_objects = [] |
| | extra_link_args = [] |
| | is_rocm_pytorch = False |
| | try: |
| | from torch.utils.cpp_extension import ROCM_HOME |
| | is_rocm_pytorch = True if ((torch.version.hip is not None) and |
| | (ROCM_HOME is not None)) else False |
| | except ImportError: |
| | pass |
| |
|
| | if os.getenv('MMCV_WITH_DIOPI', '0') == '1': |
| | import mmengine |
| | from mmengine.utils.version_utils import digit_version |
| | assert digit_version(mmengine.__version__) >= digit_version( |
| | '0.7.4'), f'mmengine >= 0.7.4 is required \ |
| | but {mmengine.__version__} is installed' |
| |
|
| | print(f'Compiling {ext_name} with CPU and DIPU') |
| | define_macros += [('MMCV_WITH_DIOPI', None)] |
| | define_macros += [('DIOPI_ATTR_WEAK', None)] |
| | op_files = glob.glob('./mmcv/ops/csrc/pytorch/*.cpp') + \ |
| | glob.glob('./mmcv/ops/csrc/pytorch/cpu/*.cpp') |
| | extension = CppExtension |
| | include_dirs.append(os.path.abspath('./mmcv/ops/csrc/common')) |
| | dipu_root = os.getenv('DIPU_ROOT') |
| | diopi_path = os.getenv('DIOPI_PATH') |
| | dipu_path = os.getenv('DIPU_PATH') |
| | vendor_include_dirs = os.getenv('VENDOR_INCLUDE_DIRS') |
| | nccl_include_dirs = os.getenv('NCCL_INCLUDE_DIRS') |
| | include_dirs.append(dipu_root) |
| | include_dirs.append(diopi_path + '/include') |
| | include_dirs.append(dipu_path + '/dist/include') |
| | include_dirs.append(vendor_include_dirs) |
| | if nccl_include_dirs: |
| | include_dirs.append(nccl_include_dirs) |
| | library_dirs += [dipu_root] |
| | libraries += ['torch_dipu'] |
| | elif is_rocm_pytorch or torch.cuda.is_available() or os.getenv( |
| | 'FORCE_CUDA', '0') == '1': |
| | if is_rocm_pytorch: |
| | define_macros += [('MMCV_WITH_HIP', None)] |
| | define_macros += [('MMCV_WITH_CUDA', None)] |
| | cuda_args = os.getenv('MMCV_CUDA_ARGS') |
| | extra_compile_args['nvcc'] = [cuda_args] if cuda_args else [] |
| | op_files = glob.glob('./mmcv/ops/csrc/pytorch/*.cpp') + \ |
| | glob.glob('./mmcv/ops/csrc/pytorch/cpu/*.cpp') + \ |
| | glob.glob('./mmcv/ops/csrc/pytorch/cuda/*.cu') + \ |
| | glob.glob('./mmcv/ops/csrc/pytorch/cuda/*.cpp') |
| | extension = CUDAExtension |
| | include_dirs.append(os.path.abspath('./mmcv/ops/csrc/pytorch')) |
| | include_dirs.append(os.path.abspath('./mmcv/ops/csrc/common')) |
| | include_dirs.append(os.path.abspath('./mmcv/ops/csrc/common/cuda')) |
| | elif (hasattr(torch, 'is_mlu_available') and |
| | torch.is_mlu_available()) or \ |
| | os.getenv('FORCE_MLU', '0') == '1': |
| | from torch_mlu.utils.cpp_extension import MLUExtension |
| |
|
| | def get_mluops_version(file_path): |
| | with open(file_path) as f: |
| | for line in f: |
| | if re.search('MLUOP_MAJOR', line): |
| | major = line.strip().split(' ')[2] |
| | if re.search('MLUOP_MINOR', line): |
| | minor = line.strip().split(' ')[2] |
| | if re.search('MLUOP_PATCHLEVEL', line): |
| | patchlevel = line.strip().split(' ')[2] |
| | mluops_version = f'v{major}.{minor}.{patchlevel}' |
| | return mluops_version |
| |
|
| | mmcv_mluops_version = get_mluops_version( |
| | './mmcv/ops/csrc/pytorch/mlu/mlu_common_helper.h') |
| | mlu_ops_path = os.getenv('MMCV_MLU_OPS_PATH') |
| | if mlu_ops_path: |
| | exists_mluops_version = get_mluops_version( |
| | mlu_ops_path + '/bangc-ops/mlu_op.h') |
| | if exists_mluops_version != mmcv_mluops_version: |
| | print('the version of mlu-ops provided is %s,' |
| | ' while %s is needed.' % |
| | (exists_mluops_version, mmcv_mluops_version)) |
| | exit() |
| | try: |
| | if os.path.exists('mlu-ops'): |
| | if os.path.islink('mlu-ops'): |
| | os.remove('mlu-ops') |
| | os.symlink(mlu_ops_path, 'mlu-ops') |
| | elif os.path.abspath('mlu-ops') != mlu_ops_path: |
| | os.symlink(mlu_ops_path, 'mlu-ops') |
| | else: |
| | os.symlink(mlu_ops_path, 'mlu-ops') |
| | except Exception: |
| | raise FileExistsError( |
| | 'mlu-ops already exists, please move it out,' |
| | 'or rename or remove it.') |
| | else: |
| | if not os.path.exists('mlu-ops'): |
| | import requests |
| | mluops_url = 'https://github.com/Cambricon/mlu-ops/' + \ |
| | 'archive/refs/tags/' + mmcv_mluops_version + '.zip' |
| | req = requests.get(mluops_url) |
| | with open('./mlu-ops.zip', 'wb') as f: |
| | try: |
| | f.write(req.content) |
| | except Exception: |
| | raise ImportError('failed to download mlu-ops') |
| |
|
| | from zipfile import BadZipFile, ZipFile |
| | with ZipFile('./mlu-ops.zip', 'r') as archive: |
| | try: |
| | archive.extractall() |
| | dir_name = archive.namelist()[0].split('/')[0] |
| | os.rename(dir_name, 'mlu-ops') |
| | except BadZipFile: |
| | print('invalid mlu-ops.zip file') |
| | else: |
| | exists_mluops_version = get_mluops_version( |
| | './mlu-ops/bangc-ops/mlu_op.h') |
| | if exists_mluops_version != mmcv_mluops_version: |
| | print('the version of provided mlu-ops is %s,' |
| | ' while %s is needed.' % |
| | (exists_mluops_version, mmcv_mluops_version)) |
| | exit() |
| |
|
| | define_macros += [('MMCV_WITH_MLU', None)] |
| | mlu_args = os.getenv('MMCV_MLU_ARGS', '-DNDEBUG ') |
| | mluops_includes = [] |
| | mluops_includes.append('-I' + |
| | os.path.abspath('./mlu-ops/bangc-ops')) |
| | mluops_includes.append( |
| | '-I' + os.path.abspath('./mlu-ops/bangc-ops/kernels')) |
| | extra_compile_args['cncc'] = [mlu_args] + \ |
| | mluops_includes if mlu_args else mluops_includes |
| | extra_compile_args['cxx'] += ['-fno-gnu-unique'] |
| | op_files = glob.glob('./mmcv/ops/csrc/pytorch/*.cpp') + \ |
| | glob.glob('./mmcv/ops/csrc/pytorch/cpu/*.cpp') + \ |
| | glob.glob('./mmcv/ops/csrc/pytorch/mlu/*.cpp') + \ |
| | glob.glob('./mmcv/ops/csrc/common/mlu/*.mlu') + \ |
| | glob.glob( |
| | './mlu-ops/bangc-ops/core/**/*.cpp', recursive=True) + \ |
| | glob.glob( |
| | './mlu-ops/bangc-ops/kernels/**/*.cpp', recursive=True) + \ |
| | glob.glob( |
| | './mlu-ops/bangc-ops/kernels/**/*.mlu', recursive=True) |
| | extra_link_args = [ |
| | '-Wl,--whole-archive', |
| | './mlu-ops/bangc-ops/kernels/kernel_wrapper/lib/libextops.a', |
| | '-Wl,--no-whole-archive' |
| | ] |
| | extension = MLUExtension |
| | include_dirs.append(os.path.abspath('./mmcv/ops/csrc/common')) |
| | include_dirs.append(os.path.abspath('./mmcv/ops/csrc/common/mlu')) |
| | include_dirs.append(os.path.abspath('./mlu-ops/bangc-ops')) |
| | elif (hasattr(torch.backends, 'mps') |
| | and torch.backends.mps.is_available()) or os.getenv( |
| | 'FORCE_MPS', '0') == '1': |
| | |
| | from distutils.unixccompiler import UnixCCompiler |
| | if '.mm' not in UnixCCompiler.src_extensions: |
| | UnixCCompiler.src_extensions.append('.mm') |
| | UnixCCompiler.language_map['.mm'] = 'objc' |
| |
|
| | define_macros += [('MMCV_WITH_MPS', None)] |
| | extra_compile_args = {} |
| | extra_compile_args['cxx'] = ['-Wall', '-std=c++17'] |
| | extra_compile_args['cxx'] += [ |
| | '-framework', 'Metal', '-framework', 'Foundation' |
| | ] |
| | extra_compile_args['cxx'] += ['-ObjC++'] |
| | |
| | op_files = glob.glob('./mmcv/ops/csrc/pytorch/*.cpp') + \ |
| | glob.glob('./mmcv/ops/csrc/pytorch/cpu/*.cpp') |
| | |
| | if parse_version(torch.__version__) < parse_version('2.1.0'): |
| | op_files += glob.glob('./mmcv/ops/csrc/common/mps/*.mm') + \ |
| | glob.glob('./mmcv/ops/csrc/pytorch/mps/*.mm') |
| | extension = CppExtension |
| | include_dirs.append(os.path.abspath('./mmcv/ops/csrc/common')) |
| | include_dirs.append(os.path.abspath('./mmcv/ops/csrc/common/mps')) |
| | elif (os.getenv('FORCE_NPU', '0') == '1'): |
| | print(f'Compiling {ext_name} only with CPU and NPU') |
| | try: |
| | from torch_npu.utils.cpp_extension import NpuExtension |
| | define_macros += [('MMCV_WITH_NPU', None)] |
| | extension = NpuExtension |
| | if parse_version(torch.__version__) <= parse_version('2.0.0'): |
| | define_macros += [('MMCV_WITH_XLA', None)] |
| | if parse_version(torch.__version__) > parse_version('2.0.0'): |
| | define_macros += [('MMCV_WITH_KPRIVATE', None)] |
| | except Exception: |
| | raise ImportError('can not find any torch_npu') |
| | |
| | op_files = glob.glob('./mmcv/ops/csrc/pytorch/*.cpp') + \ |
| | glob.glob('./mmcv/ops/csrc/pytorch/cpu/*.cpp') + \ |
| | glob.glob('./mmcv/ops/csrc/common/npu/*.cpp') + \ |
| | glob.glob('./mmcv/ops/csrc/pytorch/npu/*.cpp') |
| | include_dirs.append(os.path.abspath('./mmcv/ops/csrc/common')) |
| | include_dirs.append(os.path.abspath('./mmcv/ops/csrc/common/npu')) |
| | else: |
| | print(f'Compiling {ext_name} only with CPU') |
| | op_files = glob.glob('./mmcv/ops/csrc/pytorch/*.cpp') + \ |
| | glob.glob('./mmcv/ops/csrc/pytorch/cpu/*.cpp') |
| | extension = CppExtension |
| | include_dirs.append(os.path.abspath('./mmcv/ops/csrc/common')) |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | if 'nvcc' in extra_compile_args and platform.system() != 'Windows': |
| | if parse_version(torch.__version__) <= parse_version('1.12.1'): |
| | extra_compile_args['nvcc'] += ['-std=c++14'] |
| | else: |
| | extra_compile_args['nvcc'] += ['-std=c++17'] |
| |
|
| | ext_ops = extension( |
| | name=ext_name, |
| | sources=op_files, |
| | include_dirs=include_dirs, |
| | define_macros=define_macros, |
| | extra_objects=extra_objects, |
| | extra_compile_args=extra_compile_args, |
| | library_dirs=library_dirs, |
| | libraries=libraries, |
| | extra_link_args=extra_link_args) |
| | extensions.append(ext_ops) |
| | return extensions |
| |
|
| |
|
| | setup( |
| | name='mmcv' if os.getenv('MMCV_WITH_OPS', '1') == '1' else 'mmcv-lite', |
| | version=get_version(), |
| | description='OpenMMLab Computer Vision Foundation', |
| | keywords='computer vision', |
| | packages=find_packages(), |
| | include_package_data=True, |
| | classifiers=[ |
| | 'Development Status :: 4 - Beta', |
| | 'License :: OSI Approved :: Apache Software License', |
| | 'Operating System :: OS Independent', |
| | 'Programming Language :: Python :: 3', |
| | 'Programming Language :: Python :: 3.7', |
| | 'Programming Language :: Python :: 3.8', |
| | 'Programming Language :: Python :: 3.9', |
| | 'Programming Language :: Python :: 3.10', |
| | 'Topic :: Utilities', |
| | ], |
| | url='https://github.com/open-mmlab/mmcv', |
| | author='MMCV Contributors', |
| | author_email='openmmlab@gmail.com', |
| | install_requires=install_requires, |
| | extras_require={ |
| | 'all': parse_requirements('requirements.txt'), |
| | 'tests': parse_requirements('requirements/test.txt'), |
| | 'build': parse_requirements('requirements/build.txt'), |
| | 'optional': parse_requirements('requirements/optional.txt'), |
| | }, |
| | python_requires='>=3.7', |
| | ext_modules=get_extensions(), |
| | cmdclass=cmd_class, |
| | zip_safe=False) |
| |
|