Skip to content

Commit d8e1c00

Browse files
authored
Merge pull request #364 from bastibe/v0.12.0
Thank you, Barabazs, Andrew Murray, Jon Peirce, for contributions to this release. - Updated libsndfile to v1.2.0 - Improves precompiled library location, especially with py2app or cx-freeze. - Now provide binary wheels for Linux x86_64 - Now prefers packaged libsndfile over system-installed libsndfile
2 parents 77444fe + 07ae8fd commit d8e1c00

File tree

5 files changed

+100
-39
lines changed

5 files changed

+100
-39
lines changed

README.rst

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ interface for Python calling C code. CFFI is supported for CPython 2.6+,
3838
Breaking Changes
3939
----------------
4040

41-
The ``soundfile`` module has evolved rapidly during the last few releases. Most
41+
The ``soundfile`` module has evolved rapidly in the past. Most
4242
notably, we changed the import name from ``import pysoundfile`` to
4343
``import soundfile`` in 0.7. In 0.6, we cleaned up many small
4444
inconsistencies, particularly in the the ordering and naming of
@@ -52,17 +52,25 @@ In 0.9.0, we changed the ``ctype`` arguments of the ``buffer_*``
5252
methods to ``dtype``, using the Numpy ``dtype`` notation. The old
5353
``ctype`` arguments still work, but are now officially deprecated.
5454

55+
In 0.12.0, we changed the load order of the libsndfile library. Now,
56+
the packaged libsndfile in the platform-specific wheels is tried
57+
before falling back to any system-provided libsndfile. If you would
58+
prefer using the system-provided libsndfile, install the source
59+
package or source wheel instead of the platform-specific wheels.
60+
5561
Installation
5662
------------
5763

5864
The ``soundfile`` module depends on the Python packages CFFI and NumPy, and the
59-
system library libsndfile.
65+
library libsndfile.
6066

6167
In a modern Python, you can use ``pip install soundfile`` to download
62-
and install the latest release of the ``soundfile`` module and its dependencies.
63-
On Windows and OS X, this will also install the library libsndfile.
64-
On Linux, you need to install libsndfile using your distribution's
65-
package manager, for example ``sudo apt-get install libsndfile1``.
68+
and install the latest release of the ``soundfile`` module and its
69+
dependencies. On Windows (64/32) and OS X (Intel/ARM) and Linux 64,
70+
this will also install a current version of the library libsndfile. If
71+
you install the source module, you need to install libsndfile using
72+
your distribution's package manager, for example ``sudo apt install
73+
libsndfile1``.
6674

6775
If you are running on an unusual platform or if you are using an older
6876
version of Python, you might need to install NumPy and CFFI separately,
@@ -71,6 +79,24 @@ Binaries for Python Extension Packages <http://www.lfd.uci.edu/~gohlke/pythonlib
7179

7280
.. _Anaconda: https://www.continuum.io/downloads
7381

82+
Building
83+
--------
84+
85+
``Soundfile`` itself does not contain any compiled code and can be
86+
bundled into a wheel with the usual ``python setup.py bdist_wheel``.
87+
However, ``soundfile`` relies on libsndfile, and optionally ships its
88+
own copy of libsndfile in the wheel.
89+
90+
To build a binary wheel that contains libsndfile, make sure to
91+
checkout and update the ``_soundfile_data`` submodule, then run
92+
``python setup.py bdist_wheel`` as usual. If the resulting file size
93+
of the wheel is around one megabyte, a matching libsndfile has been
94+
bundled (without libsndfile, it's around 25 KB).
95+
96+
To build binary wheels for all supported platforms, run ``python
97+
build_wheels.py``, which will ``python setup.py bdist_wheel`` for each
98+
of the platforms we have precompiled libsndfiles for.
99+
74100
Error Reporting
75101
---------------
76102

@@ -309,3 +335,12 @@ News
309335
- Improves documentation, error messages and tests
310336
- Displays length of very short files in samples
311337
- Supports the file system path protocol (pathlib et al)
338+
339+
2023-02-02 V0.12.0 Bastian Bechtold
340+
Thank you, Barabazs, Andrew Murray, Jon Peirce, for contributions
341+
to this release.
342+
343+
- Updated libsndfile to v1.2.0
344+
- Improves precompiled library location, especially with py2app or cx-freeze.
345+
- Now provide binary wheels for Linux x86_64
346+
- Now prefers packaged libsndfile over system-installed libsndfile

build_wheels.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
architectures = dict(darwin=['x86_64', 'arm64'],
55
win32=['32bit', '64bit'],
6+
linux=['x86_64'],
67
noplatform='noarch')
78

89
def cleanup():

setup.py

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,27 @@
11
#!/usr/bin/env python
22
import os
3-
from platform import architecture
3+
from platform import architecture, machine
44
from setuptools import setup
55
from setuptools.command.test import test as TestCommand
66
import sys
77

88
# environment variables for cross-platform package creation
99
platform = os.environ.get('PYSOUNDFILE_PLATFORM', sys.platform)
10-
architecture0 = os.environ.get('PYSOUNDFILE_ARCHITECTURE', architecture()[0])
10+
architecture0 = os.environ.get('PYSOUNDFILE_ARCHITECTURE')
11+
if architecture0 is None:
12+
# follow the same decision tree as in soundfile.py after
13+
# _find_library('sndfile') fails:
14+
if sys.platform == 'win32':
15+
architecture0 = architecture()[0] # 64bit or 32bit
16+
else:
17+
architecture0 = machine() # x86_64 or arm64
1118

1219
if platform == 'darwin':
1320
libname = 'libsndfile_' + architecture0 + '.dylib'
1421
elif platform == 'win32':
1522
libname = 'libsndfile_' + architecture0 + '.dll'
23+
elif platform == 'linux':
24+
libname = 'libsndfile_' + architecture0 + '.so'
1625
else:
1726
libname = None
1827

@@ -60,24 +69,37 @@ def get_tag(self):
6069
pythons = 'py2.py3'
6170
if platform == 'darwin':
6271
if architecture0 == 'x86_64':
63-
oses = 'macosx_10_9_x86_64.macosx_11_0_x86_64'
72+
oses = 'macosx_10_9_x86_64'
6473
else:
65-
oses = 'macosx_10_9_arm64.macosx_11_0_arm64'
74+
oses = 'macosx_11_0_arm64'
6675
elif platform == 'win32':
6776
if architecture0 == '32bit':
6877
oses = 'win32'
6978
else:
7079
oses = 'win_amd64'
80+
elif platform == 'linux':
81+
# the oldest mainline github runner available is ubuntu 20.04,
82+
# which runs glibc 2.31:
83+
oses = 'manylinux_2_31_x86_64'
7184
else:
7285
pythons = 'py2.py3'
7386
oses = 'any'
7487
return pythons, 'none', oses
7588

7689
cmdclass['bdist_wheel'] = bdist_wheel_half_pure
7790

91+
with open('soundfile.py') as f:
92+
for line in f:
93+
if line.startswith('__version__'):
94+
_, soundfile_version = line.split('=')
95+
soundfile_version = soundfile_version.strip(' "\'\n')
96+
break
97+
else:
98+
raise RuntimeError("Could not find __version__ in soundfile.py")
99+
78100
setup(
79101
name='soundfile',
80-
version='0.11.0',
102+
version=soundfile_version,
81103
description='An audio library based on libsndfile, CFFI and NumPy',
82104
author='Bastian Bechtold',
83105
author_email='[email protected]',

soundfile.py

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
For further information, see https://python-soundfile.readthedocs.io/.
99
1010
"""
11-
__version__ = "0.11.0"
11+
__version__ = "0.12.0"
1212

1313
import os as _os
1414
import sys as _sys
@@ -145,48 +145,51 @@
145145
'int16': 'short'
146146
}
147147

148-
try:
149-
_libname = _find_library('sndfile')
150-
if _libname is None:
151-
raise OSError('sndfile library not found')
152-
_snd = _ffi.dlopen(_libname)
153-
except OSError:
148+
try: # packaged lib (in _soundfile_data which should be on python path)
154149
if _sys.platform == 'darwin':
155150
from platform import machine as _machine
156151
_packaged_libname = 'libsndfile_' + _machine() + '.dylib'
157-
_libname = 'libsndfile.dylib'
158152
elif _sys.platform == 'win32':
159153
from platform import architecture as _architecture
160154
_packaged_libname = 'libsndfile_' + _architecture()[0] + '.dll'
161-
_libname = 'libsndfile.dll'
162155
elif _sys.platform == 'linux':
163-
_packaged_libname = 'libsndfile.so' # not provided!
164-
_libname = 'libsndfile.so'
156+
from platform import machine as _machine
157+
_packaged_libname = 'libsndfile_' + _machine() + '.so'
165158
else:
166-
raise
167-
168-
# hack for packaging tools like cx_Freeze, which
169-
# compress all scripts into a zip file
170-
# which causes __file__ to be inside this zip file
171-
172-
_path = _os.path.dirname(_os.path.abspath(__file__))
173-
174-
while not _os.path.isdir(_path):
175-
_path = _os.path.abspath(_os.path.join(_path, '..'))
159+
raise OSError('no packaged library for this platform')
160+
161+
import _soundfile_data # ImportError if this doesn't exist
162+
_path = _os.path.dirname(_soundfile_data.__file__) # TypeError if __file__ is None
163+
_full_path = _os.path.join(_path, _packaged_libname)
164+
_snd = _ffi.dlopen(_full_path) # OSError if file doesn't exist or can't be loaded
165+
166+
except (OSError, ImportError, TypeError):
167+
try: # system-wide libsndfile:
168+
_libname = _find_library('sndfile')
169+
if _libname is None:
170+
raise OSError('sndfile library not found using ctypes.util.find_library')
171+
_snd = _ffi.dlopen(_libname)
172+
173+
except OSError:
174+
# Try explicit file name, if the general does not work (e.g. on nixos)
175+
if _sys.platform == 'darwin':
176+
_explicit_libname = 'libsndfile.dylib'
177+
elif _sys.platform == 'win32':
178+
_explicit_libname = 'libsndfile.dll'
179+
elif _sys.plaform == 'linux':
180+
_explicit_libname = 'libsndfile.so'
181+
else:
182+
raise
176183

177-
try: # packaged libsndfile:
178-
_snd = _ffi.dlopen(_os.path.join(_path, '_soundfile_data', _packaged_libname))
179-
except OSError: # try system-wide libsndfile:
180184
# Homebrew on Apple M1 uses a `/opt/homebrew/lib` instead of
181185
# `/usr/local/lib`. We are making sure we pick that up.
182186
from platform import machine as _machine
183187
if _sys.platform == 'darwin' and _machine() == 'arm64':
184188
_hbrew_path = '/opt/homebrew/lib/' if _os.path.isdir('/opt/homebrew/lib/') \
185189
else '/usr/local/lib/'
186-
_snd = _ffi.dlopen(_os.path.join(_hbrew_path, _libname))
190+
_snd = _ffi.dlopen(_os.path.join(_hbrew_path, _explicit_libname))
187191
else:
188-
# Try explicit file name, if the general does not work (e.g. on nixos)
189-
_snd = _ffi.dlopen(_libname)
192+
_snd = _ffi.dlopen(_explicit_libname)
190193

191194
__libsndfile_version__ = _ffi.string(_snd.sf_version_string()).decode('utf-8', 'replace')
192195
if __libsndfile_version__.startswith('libsndfile-'):

0 commit comments

Comments
 (0)