Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use System lz4, zstd, and blosc #569

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,12 @@ codecs for use in data storage and communication applications.

.. image:: https://codecov.io/gh/zarr-developers/numcodecs/branch/main/graph/badge.svg
:target: https://codecov.io/gh/zarr-developers/numcodecs

---
If you already have native Blosc, Zstd, and LZ4 installed on your system and want to use these system libraries instead of the vendored sources, you
should set the `NUMCODECS_USE_SYSTEM_LIBS=1` environment variable when building the wheel, like this:

$ NUMCODECS_USE_SYSTEM_LIBS=1 pip install numcodecs --no-binary numcodecs

Blosc, Zstd, and LZ4 are found via the `pkg-config` utility. Moreover, you must build all 3 `blosc`, `libzstd`, and `liblz4`
components. C-Blosc comes with full sources for LZ4, LZ4HC, Snappy, Zlib and Zstd and in general, you should not worry about not having (or CMake not finding) the libraries in your system because by default the included sources will be automatically compiled and included in the C-Blosc library. This effectively means that you can be confident in having a complete support for all the codecs in all the Blosc deployments (unless you are explicitly excluding support for some of them). To compile blosc, see these [instructions](https://github.com/Blosc/c-blosc?tab=readme-ov-file#compiling-the-blosc-library).
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ requires = [
"Cython",
"py-cpuinfo",
"numpy",
"pkgconfig"
]
build-backend = "setuptools.build_meta"

Expand Down
151 changes: 145 additions & 6 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from distutils import ccompiler
from distutils.command.clean import clean
from distutils.sysconfig import customize_compiler
import pkgconfig

# determine CPU support for SSE2 and AVX2
cpu_info = cpuinfo.get_cpu_info()
Expand All @@ -17,6 +18,7 @@
have_avx2 = 'avx2' in flags
disable_sse2 = 'DISABLE_NUMCODECS_SSE2' in os.environ
disable_avx2 = 'DISABLE_NUMCODECS_AVX2' in os.environ
use_system_libraries = 'NUMCODECS_USE_SYSTEM_LIBS' in os.environ

# setup common compile arguments
have_cflags = 'CFLAGS' in os.environ
Expand Down Expand Up @@ -49,8 +51,8 @@ def error(*msg):
print('[numcodecs]', *msg, **kwargs)


def blosc_extension():
info('setting up Blosc extension')
def _blosc_extension_with_vendored_libs():
info('setting up Blosc extension from vendored sources')

extra_compile_args = base_compile_args.copy()
define_macros = []
Expand Down Expand Up @@ -125,8 +127,68 @@ def blosc_extension():
return extensions


def zstd_extension():
info('setting up Zstandard extension')
def _blosc_extension_with_system_libs():
info('setting up Blosc extension with system libraries')

extra_compile_args = base_compile_args.copy()

blosc_package_configuration = pkgconfig.parse("blosc")

define_macros = blosc_package_configuration["define_macros"]
include_dirs = blosc_package_configuration["include_dirs"]
libraries = blosc_package_configuration["libraries"]
library_dirs = blosc_package_configuration["library_dirs"]

# remove minizip because Python.h 3.8 tries to include crypt.h
include_dirs = [d for d in include_dirs if 'minizip' not in d]

# define_macros += [('CYTHON_TRACE', '1')]

# SSE2
if have_sse2 and not disable_sse2:
info('compiling Blosc extension with SSE2 support')
extra_compile_args.append('-DSHUFFLE_SSE2_ENABLED')
if os.name == 'nt':
define_macros += [('__SSE2__', 1)]
else:
info('compiling Blosc extension without SSE2 support')

# AVX2
if have_avx2 and not disable_avx2:
info('compiling Blosc extension with AVX2 support')
extra_compile_args.append('-DSHUFFLE_AVX2_ENABLED')
if os.name == 'nt':
define_macros += [('__AVX2__', 1)]
else:
info('compiling Blosc extension without AVX2 support')

sources = ['numcodecs/blosc.pyx']

# define extension module
extensions = [
Extension(
'numcodecs.blosc',
sources=sources,
include_dirs=include_dirs,
define_macros=define_macros,
extra_compile_args=extra_compile_args,
libraries=libraries,
library_dirs=library_dirs,
),
]

return extensions


def blosc_extension():
if use_system_libraries:
return _blosc_extension_with_system_libs()
else:
return _blosc_extension_with_vendored_libs()


def _zstd_extension_with_vendored_sources():
info('setting up Zstandard extension from vendored sources')

zstd_sources = []
extra_compile_args = base_compile_args.copy()
Expand Down Expand Up @@ -167,8 +229,46 @@ def zstd_extension():
return extensions


def lz4_extension():
info('setting up LZ4 extension')
def _zstd_extension_with_system_libs():
info('setting up Zstandard extension with system libraries')

extra_compile_args = base_compile_args.copy()

zstd_package_configuration = pkgconfig.parse("libzstd")
include_dirs = zstd_package_configuration["include_dirs"]
define_macros = zstd_package_configuration["define_macros"]
libraries = zstd_package_configuration["libraries"]
library_dirs = zstd_package_configuration["library_dirs"]

# define_macros += [('CYTHON_TRACE', '1')]

sources = ['numcodecs/zstd.pyx']

# define extension module
extensions = [
Extension(
'numcodecs.zstd',
sources=sources,
include_dirs=include_dirs,
define_macros=define_macros,
extra_compile_args=extra_compile_args,
libraries=libraries,
library_dirs=library_dirs,
),
]

return extensions


def zstd_extension():
if use_system_libraries:
return _zstd_extension_with_system_libs()
else:
return _zstd_extension_with_vendored_sources()


def _lz4_extension_with_vendored_sources():
info('setting up LZ4 extension from vendored sources')

extra_compile_args = base_compile_args.copy()
define_macros = []
Expand All @@ -195,6 +295,45 @@ def lz4_extension():
return extensions


def _lz4_extension_with_system_libs():
info('setting up LZ4 extension with system libraries')

extra_compile_args = base_compile_args.copy()

lz4_package_configuration = pkgconfig.parse("liblz4")
include_dirs = lz4_package_configuration["include_dirs"]
define_macros = lz4_package_configuration["define_macros"]
libraries = lz4_package_configuration["libraries"]
library_dirs = lz4_package_configuration["library_dirs"]

include_dirs += ['numcodecs']
# define_macros += [('CYTHON_TRACE', '1')]

sources = ['numcodecs/lz4.pyx']

# define extension module
extensions = [
Extension(
'numcodecs.lz4',
sources=sources,
include_dirs=include_dirs,
define_macros=define_macros,
extra_compile_args=extra_compile_args,
libraries=libraries,
library_dirs=library_dirs,
),
]

return extensions


def lz4_extension():
if use_system_libraries:
return _lz4_extension_with_system_libs()
else:
return _lz4_extension_with_vendored_sources()


def vlen_extension():
info('setting up vlen extension')
import numpy
Expand Down