setup.py 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. #!/usr/bin/env python
  2. # Copyright (c) 2017-present, Facebook, Inc.
  3. # All rights reserved.
  4. #
  5. # This source code is licensed under the BSD-style license found in the
  6. # LICENSE file in the root directory of this source tree. An additional grant
  7. # of patent rights can be found in the PATENTS file in the same directory.
  8. from __future__ import absolute_import
  9. from __future__ import division
  10. from __future__ import print_function
  11. from __future__ import unicode_literals
  12. from setuptools import setup, Extension
  13. from setuptools.command.build_ext import build_ext
  14. import sys
  15. import setuptools
  16. import os
  17. __version__ = '0.8.22'
  18. FASTTEXT_SRC = "src"
  19. # Based on https://github.com/pybind/python_example
  20. class get_pybind_include(object):
  21. """Helper class to determine the pybind11 include path
  22. The purpose of this class is to postpone importing pybind11
  23. until it is actually installed, so that the ``get_include()``
  24. method can be invoked. """
  25. def __init__(self, user=False):
  26. self.user = user
  27. def __str__(self):
  28. import pybind11
  29. return pybind11.get_include(self.user)
  30. fasttext_src_files = map(str, os.listdir(FASTTEXT_SRC))
  31. fasttext_src_cc = list(filter(lambda x: x.endswith('.cc'), fasttext_src_files))
  32. fasttext_src_cc = list(
  33. map(lambda x: str(os.path.join(FASTTEXT_SRC, x)), fasttext_src_cc)
  34. )
  35. ext_modules = [
  36. Extension(
  37. str('fasttext_pybind'),
  38. [
  39. str('python/fastText/pybind/fasttext_pybind.cc'),
  40. ] + fasttext_src_cc,
  41. include_dirs=[
  42. # Path to pybind11 headers
  43. get_pybind_include(),
  44. get_pybind_include(user=True),
  45. # Path to fasttext source code
  46. FASTTEXT_SRC,
  47. ],
  48. language='c++',
  49. extra_compile_args=["-O3 -funroll-loops -pthread -march=native"],
  50. ),
  51. ]
  52. # As of Python 3.6, CCompiler has a `has_flag` method.
  53. # cf http://bugs.python.org/issue26689
  54. def has_flag(compiler, flags):
  55. """Return a boolean indicating whether a flag name is supported on
  56. the specified compiler.
  57. """
  58. import tempfile
  59. with tempfile.NamedTemporaryFile('w', suffix='.cpp') as f:
  60. f.write('int main (int argc, char **argv) { return 0; }')
  61. try:
  62. compiler.compile([f.name], extra_postargs=flags)
  63. except setuptools.distutils.errors.CompileError:
  64. return False
  65. return True
  66. def cpp_flag(compiler):
  67. """Return the -std=c++[0x/11/14] compiler flag.
  68. The c++14 is preferred over c++0x/11 (when it is available).
  69. """
  70. standards = ['-std=c++14', '-std=c++11', '-std=c++0x']
  71. for standard in standards:
  72. if has_flag(compiler, [standard]):
  73. return standard
  74. raise RuntimeError(
  75. 'Unsupported compiler -- at least C++0x support '
  76. 'is needed!'
  77. )
  78. class BuildExt(build_ext):
  79. """A custom build extension for adding compiler-specific options."""
  80. c_opts = {
  81. 'msvc': ['/EHsc'],
  82. 'unix': [],
  83. }
  84. def build_extensions(self):
  85. if sys.platform == 'darwin':
  86. all_flags = ['-stdlib=libc++', '-mmacosx-version-min=10.7']
  87. if has_flag(self.compiler, [all_flags[0]]):
  88. self.c_opts['unix'] += [all_flags[0]]
  89. elif has_flag(self.compiler, all_flags):
  90. self.c_opts['unix'] += all_flags
  91. else:
  92. raise RuntimeError(
  93. 'libc++ is needed! Failed to compile with {} and {}.'.
  94. format(" ".join(all_flags), all_flags[0])
  95. )
  96. ct = self.compiler.compiler_type
  97. opts = self.c_opts.get(ct, [])
  98. if ct == 'unix':
  99. opts.append('-DVERSION_INFO="%s"' % self.distribution.get_version())
  100. opts.append(cpp_flag(self.compiler))
  101. if has_flag(self.compiler, ['-fvisibility=hidden']):
  102. opts.append('-fvisibility=hidden')
  103. elif ct == 'msvc':
  104. opts.append(
  105. '/DVERSION_INFO=\\"%s\\"' % self.distribution.get_version()
  106. )
  107. for ext in self.extensions:
  108. ext.extra_compile_args = opts
  109. build_ext.build_extensions(self)
  110. def _get_readme():
  111. """
  112. Use pandoc to generate rst from md.
  113. pandoc --from=markdown --to=rst --output=python/README.rst python/README.md
  114. """
  115. with open("python/README.rst") as fid:
  116. return fid.read()
  117. setup(
  118. name='fasttext',
  119. version=__version__,
  120. author='Christian Puhrsch',
  121. author_email='[email protected]',
  122. description='fastText Python bindings',
  123. long_description=_get_readme(),
  124. ext_modules=ext_modules,
  125. url='https://github.com/facebookresearch/fastText',
  126. license='BSD',
  127. classifiers=[
  128. 'Development Status :: 3 - Alpha',
  129. 'Intended Audience :: Developers',
  130. 'Intended Audience :: Science/Research',
  131. 'License :: OSI Approved :: MIT License',
  132. 'Programming Language :: Python :: 2.7',
  133. 'Programming Language :: Python :: 3.4',
  134. 'Programming Language :: Python :: 3.5',
  135. 'Programming Language :: Python :: 3.6',
  136. 'Topic :: Software Development',
  137. 'Topic :: Scientific/Engineering',
  138. 'Operating System :: Microsoft :: Windows',
  139. 'Operating System :: POSIX',
  140. 'Operating System :: Unix',
  141. 'Operating System :: MacOS',
  142. ],
  143. install_requires=['pybind11>=2.2', "setuptools >= 0.7.0", "numpy"],
  144. cmdclass={'build_ext': BuildExt},
  145. packages=[
  146. str('fastText'),
  147. str('fastText.util'),
  148. str('fastText.tests'),
  149. ],
  150. package_dir={str(''): str('python')},
  151. zip_safe=False,
  152. )