1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
|
#!/usr/bin/env python
import platform
import sys
from setuptools.command.build_ext import build_ext
from sysconfig import get_path
from setuptools import Extension, setup, find_packages
from pathlib import Path
import numpy
from Cython.Build import cythonize
from Cython.Compiler import Options
# Preserve `__doc__` on functions and classes
# http://docs.cython.org/en/latest/src/userguide/source_files_and_compilation.html#compiler-options
Options.docstrings = True
ACCELERATE = "thinc.backends._accelerate"
APPLE_OPS = ["thinc.backends.apple_ops", ACCELERATE]
PACKAGES = find_packages()
MOD_NAMES = [
"thinc.backends.cblas",
"thinc.backends.numpy_ops",
"thinc.layers.sparselinear",
"thinc.layers.premap_ids",
] + (APPLE_OPS if platform.system() == "Darwin" else [])
COMPILE_OPTIONS = {
"msvc": ["/Ox", "/EHsc"],
"other": ["-O3", "-Wno-strict-prototypes", "-Wno-unused-function", "-std=c++11"],
}
COMPILER_DIRECTIVES = {
"language_level": 3,
"embedsignature": True,
"annotation_typing": False,
"profile": sys.version_info < (3, 12),
}
LINK_OPTIONS = {"msvc": [], "other": []}
# By subclassing build_extensions we have the actual compiler that will be used
# which is really known only after finalize_options
# http://stackoverflow.com/questions/724664/python-distutils-how-to-get-a-compiler-that-is-going-to-be-used
class build_ext_options:
def build_options(self):
if hasattr(self.compiler, "initialize"):
self.compiler.initialize()
self.compiler.platform = sys.platform[:6]
for e in self.extensions:
e.extra_compile_args = COMPILE_OPTIONS.get(
self.compiler.compiler_type, COMPILE_OPTIONS["other"]
)
e.extra_link_args = LINK_OPTIONS.get(
self.compiler.compiler_type, LINK_OPTIONS["other"]
)
class build_ext_subclass(build_ext, build_ext_options):
def build_extensions(self):
build_ext_options.build_options(self)
build_ext.build_extensions(self)
def clean(path):
for path in path.glob("**/*"):
if path.is_file() and path.suffix in (".so", ".cpp"):
print(f"Deleting {path.name}")
path.unlink()
def setup_package():
root = Path(__file__).parent
if len(sys.argv) > 1 and sys.argv[1] == "clean":
return clean(root / "thinc")
with (root / "thinc" / "about.py").open("r") as f:
about = {}
exec(f.read(), about)
include_dirs = [numpy.get_include(), get_path("include")]
ext_modules = []
for name in MOD_NAMES:
mod_path = name.replace(".", "/") + ".pyx"
if name == ACCELERATE:
ext = Extension(
name,
[mod_path],
language="c++",
include_dirs=include_dirs,
libraries=["blas"],
)
else:
ext = Extension(name, [mod_path], language="c++", include_dirs=include_dirs)
ext_modules.append(ext)
print("Cythonizing sources")
ext_modules = cythonize(
ext_modules, compiler_directives=COMPILER_DIRECTIVES, language_level=2
)
setup(
name="thinc",
packages=PACKAGES,
version=about["__version__"],
ext_modules=ext_modules,
cmdclass={"build_ext": build_ext_subclass},
package_data={"": ["*.pyx", "*.pxd", "*.pxi", "*.cu", "*.hh"]},
)
if __name__ == "__main__":
setup_package()
|