-
Notifications
You must be signed in to change notification settings - Fork 112
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
Distribute PySoundFile as wheels #116
Conversation
If pysoundfile is not installed as a wheel, and libsndfile is not present on the system, this will fail in the exception handler where it tries to In an alternative implementation, we could change pysoundfile into a package, and use |
|
||
if platform == 'win32' and architecture()[0] == '32bit': | ||
shutil.copy2('win/sndfile32.dll', 'win/sndfile.dll') | ||
sndfile = [('', ['win/sndfile.dll', 'win/sndfile_license'])] | ||
sndfile = [('lib', ['win32/libsndfile.dll', 'win32/sndfile_license'])] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not keep the DLL install directory as before (i.e. ''
)? If you don't use a subdirectory, you don't need to do the path manipulation abomination in dlopen()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
''
is the Python root, not the PySoundFile root. It would be the only binary in that path. At least in lib
, it is among other libraries.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That looks promising, but I have a few comments:
You could catch the second exception, set a flag and ignore the exception.
Would this actually change anything? |
Because the Windows installer puts it in a different place than the wheel. The Windows installer puts the library in the PySoundFile root, whereas the wheel puts it into the environment root. The environment root is not a good place for the library.
True. Just don't use the |
When I tried it, it was put into the exact same directory (Windows 7, Pyzo 2013c).
I wouldn't really care. It's Windows, after all. Nothing in Windows is in a good place. The real problem, though, is if the option I guess with the .exe installer a similar option wasn't even possible, right?
Does that mean we have to provide many binary wheels? |
We'll have to provide a Windows64, Windows32, and Mac wheel. I think I got confused with the
This can actually be solved by converting PySoundFile to a package, since packages can ship |
Here's a different idea: I moved all binaries into their own package. This installs them alongside |
This idea leads to a pretty nice side benefit: We can move the
|
elif platform == 'darwin': | ||
snd = ffi.dlopen(join(dirname(__file__), 'darwin/libsndfile')) | ||
else: | ||
raise err |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should just use raise
.
Otherwise, you're losing the original traceback information.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True. Thank you.
I wasn't aware that I like the idea with the separate I still don't know how a wheel can be created that works for all Python interpreters on Win64. |
from os.path import join, dirname | ||
|
||
if platform == 'win32' and architecture()[0] == '32bit': | ||
snd = ffi.dlopen(join(dirname(__file__), 'win32/libsndfile')) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should rename the directories to win32_32bit
, win32_64bit
and darwin_64bit
, respectively.
Then you can avoid most of the repetition:
if platform in ('darwin', 'win32'):
... platform + '_' + architecture()[0] ...
else:
raise
I think it can, but the base directory must still be in the system path (?), which it probably normally isn't. When I tried it on Windows, it didn't work because of this, so you should add I suggest something like this if platform in ('darwin', 'win32'):
_snd = _ffi.dlopen(_os.path.join(
_os.path.dirname(_os.path.abspath(__file__)),
'pysoundfile_binaries',
_platform + '_' + _architecture()[0],
'libsndfile'))
else:
raise
Indeed! But for now, I don't see a better way ... |
After some experimenting and some web browsing, I think I'm starting to understand what a "pure" wheel is: there is no such thing! There is only the setting
The funny thing is, if we extend I think we should just create a presumably "pure" wheel for each supported platform (win32, win64, mac64) which will initially have a generic name (e.g. Note that this, contrary to what I expected, doesn't work with For OSX, we'll have to add a whole lot of different tags to the file name. Once we upload our 3 wheels (plus probably an actually "pure" wheel without any binaries that can be used on Linux: I think we should use something like this in if platform in ('darwin', 'win32'):
subdir = platform + '_' + architecture()[0]
extension = '.dylib' if platform == 'darwin' else '.dll'
packages = ['pysoundfile_binaries']
package_data = {'pysoundfile_binaries': [
os.path.join(subdir, 'libsndfile' + extension),
os.path.join(subdir, 'libsndfile_license')
]}
else:
packages = None
package_data = None
...
setup(
...
packages=packages,
package_data=package_data,
...
) This should also put the license into the right subdirectory (and make the superfluous copy of it obsolete). |
Hmmm, there is still the question how we get the renamed wheels uploaded to PyPI ... |
OK, a few more findings: With pip >= 6.0 the OSX tags probably become a bit less of a mess: We can probably use "twine" to upload the renamed wheels: https://pypi.python.org/pypi/twine All this is from the very interesting page https://github.com/MacPython/wiki/wiki/Spinning-wheels. |
I'll look into this this weekend. But it seems that "pure" really means "not a CPython extension", which would be applicable to PySoundFile. |
What was the reason for the 32/64-bit subdirectories? Then we could use this in if platform in ('darwin', 'win32'):
extension = '.dylib' if platform == 'darwin' else '.dll'
packages = ['pysoundfile_data']
package_data = {'pysoundfile_data': [
'libsndfile_' + architecture()[0] + extension,
'libsndfile_license'
]}
else:
packages = None
package_data = None And in try:
_snd = _ffi.dlopen('sndfile')
except OSError as err:
if _sys.platform in ('darwin', 'win32'):
from platform import architecture as _architecture
_snd = _ffi.dlopen(_os.path.join(
_os.path.dirname(_os.path.abspath(__file__)),
'pysoundfile_data', 'libsndfile_' + _architecture()[0]))
else:
raise |
To allow cross-platform wheel builds, we could add something like this to platform = os.environ.get('PYSOUNDFILE_PLATFORM', platform)
architecture0 = os.environ.get('PYSOUNDFILE_ARCHITECTURE', architecture()[0]) To be used like this:
|
8f3869c
to
d08139e
Compare
So far, I was unable to find a way for including a full set of libraries in the wheel. The homebrew-provided libsndfile depends on system libraries, but copying those system libraries into pysoundfile_binaries doesn't help. I have not found a way of producing a statically-linked version of libsndfile, either (there doesn't seem to be a switch in configure or makefile to allow this). I could build a version of libsndfile that does not link to flac, ogg, or vorbis. Also, delocate can't fix the problem, since it only patches python extensions, but not the included libsndfile library. |
The current solution should work for Windows, though. Except it doesn't, because |
if platform in ('darwin', 'win32'): | ||
packages = ['pysoundfile_binaries'] | ||
package_data = {'pysoundfile_binaries': | ||
['pysoundfile_binaries/libsndfile_license']} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the repetition of pysoundfile_binaries
intentional?
For me it doesn't work like this.
Could you please share the error message? BTW, you don't need to use Windows at all (see https://github.com/bastibe/PySoundFile/pull/116#issuecomment-86726184). |
This is a prototype of a project structure that allows for wheel distribution.
Run
python setup.py bdist_wheel --universal
to create the wheel, thenpip install {filename}.whl
to install it. I don't know how this interacts with PyPi yet.This should also fix most of the issues in #47, and remove the copying of files. It doesn't solve the need to ship binaries with the repository yet.
I don't particularly like the change to
soundfile.py
, but I haven't found a better solution yet.