You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
153 lines
6.0 KiB
153 lines
6.0 KiB
2 years ago
|
import os
|
||
|
import platform
|
||
|
import subprocess
|
||
|
from pathlib import Path
|
||
|
|
||
|
import distutils.sysconfig
|
||
|
from setuptools import Extension
|
||
|
from setuptools.command.build_ext import build_ext
|
||
|
|
||
|
__all__ = [
|
||
|
"get_ext_modules",
|
||
|
"CMakeBuild",
|
||
|
]
|
||
|
|
||
|
_THIS_DIR = Path(__file__).parent.resolve()
|
||
|
_ROOT_DIR = _THIS_DIR.parent.parent.resolve()
|
||
|
_PADDLESPEECH_DIR = _ROOT_DIR / "paddleaudio"
|
||
|
|
||
|
|
||
|
def _get_build(var, default=False):
|
||
|
if var not in os.environ:
|
||
|
return default
|
||
|
|
||
|
val = os.environ.get(var, "0")
|
||
|
trues = ["1", "true", "TRUE", "on", "ON", "yes", "YES"]
|
||
|
falses = ["0", "false", "FALSE", "off", "OFF", "no", "NO"]
|
||
|
if val in trues:
|
||
|
return True
|
||
|
if val not in falses:
|
||
|
print(f"WARNING: Unexpected environment variable value `{var}={val}`. "
|
||
|
f"Expected one of {trues + falses}")
|
||
|
return False
|
||
|
|
||
|
|
||
|
_BUILD_SOX = False if platform.system() == "Windows" else _get_build(
|
||
|
"BUILD_SOX", True)
|
||
|
_BUILD_MAD = _get_build("BUILD_MAD", False)
|
||
|
_BUILD_KALDI = False if platform.system() == "Windows" else _get_build(
|
||
|
"BUILD_KALDI", True)
|
||
|
_PADDLESPEECH_CUDA_ARCH_LIST = os.environ.get("PADDLESPEECH_CUDA_ARCH_LIST",
|
||
|
None)
|
||
|
|
||
|
def get_ext_modules():
|
||
|
if platform.system() == "Windows":
|
||
|
return []
|
||
|
modules = [
|
||
|
Extension(name="paddleaudio.lib.libpaddleaudio", sources=[]),
|
||
|
Extension(name="paddleaudio._paddleaudio", sources=[]),
|
||
|
]
|
||
|
return modules
|
||
|
|
||
|
|
||
|
# Based off of
|
||
|
# https://github.com/pybind/cmake_example/blob/580c5fd29d4651db99d8874714b07c0c49a53f8a/setup.py
|
||
|
class CMakeBuild(build_ext):
|
||
|
def run(self):
|
||
|
try:
|
||
|
subprocess.check_output(["cmake", "--version"])
|
||
|
except OSError:
|
||
|
raise RuntimeError("CMake is not available.") from None
|
||
|
super().run()
|
||
|
|
||
|
def build_extension(self, ext):
|
||
|
# Since two library files (libpaddleaudio and _paddleaudio) need to be
|
||
|
# recognized by setuptools, we instantiate `Extension` twice. (see `get_ext_modules`)
|
||
|
# This leads to the situation where this `build_extension` method is called twice.
|
||
|
# However, the following `cmake` command will build all of them at the same time,
|
||
|
# so, we do not need to perform `cmake` twice.
|
||
|
# Therefore we call `cmake` only for `paddleaudio._paddleaudio`.
|
||
|
if ext.name != "paddleaudio._paddleaudio":
|
||
|
return
|
||
|
|
||
|
extdir = os.path.abspath(
|
||
|
os.path.dirname(self.get_ext_fullpath(ext.name)))
|
||
|
|
||
|
# required for auto-detection of auxiliary "native" libs
|
||
|
if not extdir.endswith(os.path.sep):
|
||
|
extdir += os.path.sep
|
||
|
|
||
|
cfg = "Debug" if self.debug else "Release"
|
||
|
|
||
|
cmake_args = [
|
||
|
f"-DCMAKE_BUILD_TYPE={cfg}",
|
||
|
# f"-DCMAKE_PREFIX_PATH={torch.utils.cmake_prefix_path}",
|
||
|
f"-DCMAKE_INSTALL_PREFIX={extdir}",
|
||
|
"-DCMAKE_VERBOSE_MAKEFILE=ON",
|
||
|
f"-DPYTHON_INCLUDE_DIR={distutils.sysconfig.get_python_inc()}",
|
||
|
#f"-DPYTHON_LIBRARY={distutils.sysconfig.get_config_var('LIBDIR')}",
|
||
|
f"-DBUILD_SOX:BOOL={'ON' if _BUILD_SOX else 'OFF'}",
|
||
|
f"-DBUILD_MAD:BOOL={'ON' if _BUILD_MAD else 'OFF'}",
|
||
|
f"-DBUILD_KALDI:BOOL={'ON' if _BUILD_KALDI else 'OFF'}",
|
||
|
# f"-DBUILD_RNNT:BOOL={'ON' if _BUILD_RNNT else 'OFF'}",
|
||
|
# f"-DBUILD_CTC_DECODER:BOOL={'ON' if _BUILD_CTC_DECODER else 'OFF'}",
|
||
|
"-DBUILD_PADDLEAUDIO_PYTHON_EXTENSION:BOOL=ON",
|
||
|
# f"-DUSE_ROCM:BOOL={'ON' if _USE_ROCM else 'OFF'}",
|
||
|
# f"-DUSE_CUDA:BOOL={'ON' if _USE_CUDA else 'OFF'}",
|
||
|
# f"-DUSE_OPENMP:BOOL={'ON' if _USE_OPENMP else 'OFF'}",
|
||
|
# f"-DUSE_FFMPEG:BOOL={'ON' if _USE_FFMPEG else 'OFF'}",
|
||
|
]
|
||
|
build_args = ["--target", "install"]
|
||
|
# Pass CUDA architecture to cmake
|
||
|
if _PADDLESPEECH_CUDA_ARCH_LIST is not None:
|
||
|
# Convert MAJOR.MINOR[+PTX] list to new style one
|
||
|
# defined at https://cmake.org/cmake/help/latest/prop_tgt/CUDA_ARCHITECTURES.html
|
||
|
_arches = _PADDLESPEECH_CUDA_ARCH_LIST.replace(".", "").replace(
|
||
|
" ", ";").split(";")
|
||
|
_arches = [
|
||
|
arch[:-4] if arch.endswith("+PTX") else f"{arch}-real"
|
||
|
for arch in _arches
|
||
|
]
|
||
|
cmake_args += [f"-DCMAKE_CUDA_ARCHITECTURES={';'.join(_arches)}"]
|
||
|
|
||
|
# Default to Ninja
|
||
|
if "CMAKE_GENERATOR" not in os.environ or platform.system() == "Windows":
|
||
|
cmake_args += ["-GNinja"]
|
||
|
|
||
|
if platform.system() == "Windows":
|
||
|
import sys
|
||
|
|
||
|
python_version = sys.version_info
|
||
|
cmake_args += [
|
||
|
"-DCMAKE_C_COMPILER=cl",
|
||
|
"-DCMAKE_CXX_COMPILER=cl",
|
||
|
f"-DPYTHON_VERSION={python_version.major}.{python_version.minor}",
|
||
|
]
|
||
|
|
||
|
# Set CMAKE_BUILD_PARALLEL_LEVEL to control the parallel build level
|
||
|
# across all generators.
|
||
|
if "CMAKE_BUILD_PARALLEL_LEVEL" not in os.environ:
|
||
|
# self.parallel is a Python 3 only way to set parallel jobs by hand
|
||
|
# using -j in the build_ext call, not supported by pip or PyPA-build.
|
||
|
if hasattr(self, "parallel") and self.parallel:
|
||
|
# CMake 3.12+ only.
|
||
|
build_args += ["-j{}".format(self.parallel)]
|
||
|
|
||
|
if not os.path.exists(self.build_temp):
|
||
|
os.makedirs(self.build_temp)
|
||
|
|
||
|
print(
|
||
|
f"cmake {_ROOT_DIR} {' '.join(cmake_args)}, cwd={self.build_temp}")
|
||
|
subprocess.check_call(
|
||
|
["cmake", str(_ROOT_DIR)] + cmake_args, cwd=self.build_temp)
|
||
|
print(f"cmake --build . {' '.join(build_args)}, cwd={self.build_temp}")
|
||
|
subprocess.check_call(
|
||
|
["cmake", "--build", "."] + build_args, cwd=self.build_temp)
|
||
|
|
||
|
def get_ext_filename(self, fullname):
|
||
|
ext_filename = super().get_ext_filename(fullname)
|
||
|
ext_filename_parts = ext_filename.split(".")
|
||
|
without_abi = ext_filename_parts[:-2] + ext_filename_parts[-1:]
|
||
|
ext_filename = ".".join(without_abi)
|
||
|
return ext_filename
|