setup.py 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. ########################################################################
  2. #
  3. # License: BSD
  4. # Created: August 16, 2012
  5. # Author: Francesc Alted - francesc@blosc.org
  6. #
  7. ########################################################################
  8. from __future__ import absolute_import
  9. from sys import version_info as v
  10. # Check this Python version is supported
  11. if any([v < (2, 7), (3,) < v < (3, 5)]):
  12. raise Exception("Unsupported Python version %d.%d. Requires Python >= 2.7 "
  13. "or >= 3.5." % v[:2])
  14. import os
  15. from glob import glob
  16. import sys
  17. from setuptools import setup, Extension, find_packages
  18. from pkg_resources import resource_filename
  19. # For guessing the capabilities of the CPU for C-Blosc
  20. try:
  21. # Currently just Intel and some ARM archs are supported by cpuinfo module
  22. import cpuinfo
  23. cpu_info = cpuinfo.get_cpu_info()
  24. except:
  25. cpu_info = {'flags': []}
  26. class LazyCommandClass(dict):
  27. """
  28. Lazy command class that defers operations requiring Cython and numpy until
  29. they've actually been downloaded and installed by setup_requires.
  30. """
  31. def __contains__(self, key):
  32. return (
  33. key == 'build_ext'
  34. or super(LazyCommandClass, self).__contains__(key)
  35. )
  36. def __setitem__(self, key, value):
  37. if key == 'build_ext':
  38. raise AssertionError("build_ext overridden!")
  39. super(LazyCommandClass, self).__setitem__(key, value)
  40. def __getitem__(self, key):
  41. if key != 'build_ext':
  42. return super(LazyCommandClass, self).__getitem__(key)
  43. from Cython.Distutils import build_ext as cython_build_ext
  44. class build_ext(cython_build_ext):
  45. """
  46. Custom build_ext command that lazily adds numpy's include_dir to
  47. extensions.
  48. """
  49. def build_extensions(self):
  50. """
  51. Lazily append numpy's include directory to Extension includes.
  52. This is done here rather than at module scope because setup.py
  53. may be run before numpy has been installed, in which case
  54. importing numpy and calling `numpy.get_include()` will fail.
  55. """
  56. numpy_incl = resource_filename('numpy', 'core/include')
  57. for ext in self.extensions:
  58. ext.include_dirs.append(numpy_incl)
  59. # This explicitly calls the superclass method rather than the
  60. # usual super() invocation because distutils' build_class, of
  61. # which Cython's build_ext is a subclass, is an old-style class
  62. # in Python 2, which doesn't support `super`.
  63. cython_build_ext.build_extensions(self)
  64. return build_ext
  65. # Global variables
  66. CFLAGS = os.environ.get('CFLAGS', '').split()
  67. LFLAGS = os.environ.get('LFLAGS', '').split()
  68. # Allow setting the Blosc dir if installed in the system
  69. BLOSC_DIR = os.environ.get('BLOSC_DIR', '')
  70. # Sources & libraries
  71. inc_dirs = ['bcolz']
  72. lib_dirs = []
  73. libs = []
  74. def_macros = []
  75. sources = ['bcolz/carray_ext.pyx']
  76. optional_libs = []
  77. # Handle --blosc=[PATH] --lflags=[FLAGS] --cflags=[FLAGS]
  78. args = sys.argv[:]
  79. for arg in args:
  80. if arg.find('--blosc=') == 0:
  81. BLOSC_DIR = os.path.expanduser(arg.split('=')[1])
  82. sys.argv.remove(arg)
  83. if arg.find('--lflags=') == 0:
  84. LFLAGS = arg.split('=')[1].split()
  85. sys.argv.remove(arg)
  86. if arg.find('--cflags=') == 0:
  87. CFLAGS = arg.split('=')[1].split()
  88. sys.argv.remove(arg)
  89. if BLOSC_DIR != '':
  90. # Using the Blosc library
  91. lib_dirs += [os.path.join(BLOSC_DIR, 'lib')]
  92. inc_dirs += [os.path.join(BLOSC_DIR, 'include')]
  93. libs += ['blosc']
  94. else:
  95. # Compiling everything from sources
  96. sources += [f for f in glob('c-blosc/blosc/*.c')
  97. if 'avx2' not in f and 'sse2' not in f]
  98. sources += glob('c-blosc/internal-complibs/lz4*/*.c')
  99. sources += glob('c-blosc/internal-complibs/snappy*/*.cc')
  100. sources += glob('c-blosc/internal-complibs/zlib*/*.c')
  101. sources += glob('c-blosc/internal-complibs/zstd*/*/*.c')
  102. inc_dirs += [os.path.join('c-blosc', 'blosc')]
  103. inc_dirs += [d for d in glob('c-blosc/internal-complibs/*')
  104. if os.path.isdir(d)]
  105. inc_dirs += [d for d in glob('c-blosc/internal-complibs/zstd*/*')
  106. if os.path.isdir(d)]
  107. def_macros += [('HAVE_LZ4', 1), ('HAVE_SNAPPY', 1), ('HAVE_ZLIB', 1),
  108. ('HAVE_ZSTD', 1)]
  109. # Guess SSE2 or AVX2 capabilities
  110. # SSE2
  111. if 'DISABLE_BCOLZ_SSE2' not in os.environ and 'sse2' in cpu_info['flags']:
  112. print('SSE2 detected')
  113. CFLAGS.append('-DSHUFFLE_SSE2_ENABLED')
  114. sources += [f for f in glob('c-blosc/blosc/*.c') if 'sse2' in f]
  115. if os.name == 'posix':
  116. CFLAGS.append('-msse2')
  117. elif os.name == 'nt':
  118. def_macros += [('__SSE2__', 1)]
  119. # AVX2
  120. if 'DISABLE_BCOLZ_AVX2' not in os.environ and 'avx2' in cpu_info['flags']:
  121. print('AVX2 detected')
  122. CFLAGS.append('-DSHUFFLE_AVX2_ENABLED')
  123. sources += [f for f in glob('c-blosc/blosc/*.c') if 'avx2' in f]
  124. if os.name == 'posix':
  125. CFLAGS.append('-mavx2')
  126. elif os.name == 'nt':
  127. def_macros += [('__AVX2__', 1)]
  128. tests_require = []
  129. if v < (3,):
  130. tests_require.extend(['unittest2', 'mock'])
  131. # compile and link code instrumented for coverage analysis
  132. if os.getenv('TRAVIS') and os.getenv('CI') and v[0:2] == (2, 7):
  133. CFLAGS.extend(["-fprofile-arcs", "-ftest-coverage"])
  134. LFLAGS.append("-lgcov")
  135. setup(
  136. name="bcolz",
  137. use_scm_version={
  138. 'version_scheme': 'guess-next-dev',
  139. 'local_scheme': 'dirty-tag',
  140. 'write_to': 'bcolz/version.py'
  141. },
  142. description='columnar and compressed data containers.',
  143. long_description="""\
  144. bcolz provides columnar and compressed data containers. Column
  145. storage allows for efficiently querying tables with a large number of
  146. columns. It also allows for cheap addition and removal of column. In
  147. addition, bcolz objects are compressed by default for reducing
  148. memory/disk I/O needs. The compression process is carried out
  149. internally by Blosc, a high-performance compressor that is optimized
  150. for binary data.
  151. """,
  152. classifiers=[
  153. 'Development Status :: 5 - Production/Stable',
  154. 'Intended Audience :: Developers',
  155. 'Intended Audience :: Information Technology',
  156. 'Intended Audience :: Science/Research',
  157. 'License :: OSI Approved :: BSD License',
  158. 'Programming Language :: Python',
  159. 'Topic :: Software Development :: Libraries :: Python Modules',
  160. 'Operating System :: Microsoft :: Windows',
  161. 'Operating System :: Unix',
  162. 'Programming Language :: Python :: 2',
  163. 'Programming Language :: Python :: 2.7',
  164. 'Programming Language :: Python :: 3',
  165. 'Programming Language :: Python :: 3.5',
  166. 'Programming Language :: Python :: 3.6',
  167. ],
  168. author='Francesc Alted',
  169. author_email='francesc@blosc.org',
  170. maintainer='Francesc Alted',
  171. maintainer_email='francesc@blosc.org',
  172. url='https://github.com/Blosc/bcolz',
  173. license='BSD',
  174. platforms=['any'],
  175. ext_modules=[
  176. Extension(
  177. 'bcolz.carray_ext',
  178. include_dirs=inc_dirs,
  179. define_macros=def_macros,
  180. sources=sources,
  181. library_dirs=lib_dirs,
  182. libraries=libs,
  183. extra_link_args=LFLAGS,
  184. extra_compile_args=CFLAGS
  185. )
  186. ],
  187. install_requires=['numpy>=1.7'],
  188. setup_requires=[
  189. 'cython>=0.22',
  190. 'numpy>=1.7',
  191. 'setuptools>18.0',
  192. 'setuptools-scm>1.5.4'
  193. ],
  194. tests_require=tests_require,
  195. extras_require=dict(
  196. optional=[
  197. 'numexpr>=2.5.2',
  198. 'dask>=0.9.0',
  199. 'pandas',
  200. 'tables'
  201. ],
  202. test=tests_require
  203. ),
  204. packages=find_packages(),
  205. package_data={'bcolz': ['carray_ext.pxd']},
  206. cmdclass=LazyCommandClass(),
  207. )