Skip to main content

Move OSX dynamic libraries into package

Project description

https://travis-ci.org/matthew-brett/delocate.svg?branch=master

Delocate

OSX utilities to:

  • find dynamic libraries imported from python extensions

  • copy needed dynamic libraries to directory within package

  • update OSX install_names and rpath to cause code to load from copies of libraries

Provides scripts:

  • delocate-listdeps – show libraries a tree depends on

  • delocate-path – copy libraries a tree depends on into the tree and relink

  • delocate-wheel – rewrite wheel having copied and relinked library dependencies into the wheel tree.

The problem

Let’s say you have built a wheel somewhere, but it’s linking to dynamic libraries elsewhere on the machine, so you can’t distribute it, because others may not have these same libraries. Here we analyze the dependencies for a scipy wheel:

$ delocate-listdeps scipy-0.14.0b1-cp34-cp34m-macosx_10_6_intel.whl
/usr/local/Cellar/gfortran/4.8.2/gfortran/lib/libgcc_s.1.dylib
/usr/local/Cellar/gfortran/4.8.2/gfortran/lib/libgfortran.3.dylib
/usr/local/Cellar/gfortran/4.8.2/gfortran/lib/libquadmath.0.dylib

By default, this does not include libraries in /usr/lib and /System. See those too with:

$ delocate-listdeps --all scipy-0.14.0-cp34-cp34m-macosx_10_6_intel.whl
/System/Library/Frameworks/Accelerate.framework/Versions/A/Accelerate
/usr/lib/libSystem.B.dylib
/usr/lib/libstdc++.6.dylib
/usr/local/Cellar/gfortran/4.8.2/gfortran/lib/libgcc_s.1.dylib
/usr/local/Cellar/gfortran/4.8.2/gfortran/lib/libgfortran.3.dylib
/usr/local/Cellar/gfortran/4.8.2/gfortran/lib/libquadmath.0.dylib

The output tells me that scipy has picked up dynamic libraries from my homebrew installation of gfortran (as well as the system libs).

You can get a listing of the files depending on each of the libraries, using the --depending flag:

$ delocate-listdeps --depending scipy-0.14.0-cp34-cp34m-macosx_10_6_intel.whl
/usr/local/Cellar/gfortran/4.8.2/gfortran/lib/libgcc_s.1.dylib:
    scipy/interpolate/dfitpack.so
    scipy/special/specfun.so
    scipy/interpolate/_fitpack.so
    ...

A solution

We can fix like this:

$ delocate-wheel -w fixed_wheels -v scipy-0.14.0-cp34-cp34m-macosx_10_6_intel.whl
Fixing: scipy-0.14.0-cp34-cp34m-macosx_10_6_intel.whl
Copied to package .dylibs directory:
    /usr/local/Cellar/gfortran/4.8.2/gfortran/lib/libgcc_s.1.dylib
    /usr/local/Cellar/gfortran/4.8.2/gfortran/lib/libgfortran.3.dylib
    /usr/local/Cellar/gfortran/4.8.2/gfortran/lib/libquadmath.0.dylib

The -w flag tells delocate-wheel to output to a new wheel directory instead of overwriting the old wheel. -v (verbose) tells you what delocate-wheel is doing. In this case it has made a new directory in the wheel zipfile, named scipy/.dylibs. It has copied all the library dependencies that are outside the OSX system trees into this directory, and patched the python .so extensions in the wheel to use these copies instead of looking in /usr/local/Cellar/gfortran/4.8.2/gfortran/lib.

Check the links again to confirm:

$ delocate-listdeps --all fixed_wheels/scipy-0.14.0-cp34-cp34m-macosx_10_6_intel.whl
/System/Library/Frameworks/Accelerate.framework/Versions/A/Accelerate
/usr/lib/libSystem.B.dylib
/usr/lib/libstdc++.6.0.9.dylib
@loader_path/../../../../.dylibs/libgcc_s.1.dylib
@loader_path/../../../../.dylibs/libgfortran.3.dylib
@loader_path/../../../../.dylibs/libquadmath.0.dylib
@loader_path/../../../.dylibs/libgcc_s.1.dylib
@loader_path/../../../.dylibs/libgfortran.3.dylib
@loader_path/../../../.dylibs/libquadmath.0.dylib
@loader_path/../../.dylibs/libgcc_s.1.dylib
@loader_path/../../.dylibs/libgfortran.3.dylib
@loader_path/../../.dylibs/libquadmath.0.dylib
@loader_path/../.dylibs/libgcc_s.1.dylib
@loader_path/../.dylibs/libgfortran.3.dylib
@loader_path/../.dylibs/libquadmath.0.dylib
@loader_path/libgcc_s.1.dylib
@loader_path/libquadmath.0.dylib

So - system dylibs the same, but the others moved into the wheel tree.

This makes the wheel more likely to work on another machine which does not have the same version of gfortran installed - in this example.

Checking required architectures

Current Python.org Python and the OSX system Python (/usr/bin/python) are both dual Intel architecture binaries. For example:

$ lipo -info /usr/bin/python
Architectures in the fat file: /usr/bin/python are: x86_64 i386

This means that wheels built for Python.org Python or system Python should also have i386 and x86_64 versions of the Python extensions and their libraries. It is easy to link Python extensions against single architecture libraries by mistake, and therefore get single architecture extensions and / or libraries. In fact my scipy wheel is one such example, because I inadvertently linked against the homebrew libraries, which are x86_64 only. To check this you can use the --require-archs flag:

$ delocate-wheel --require-archs=intel scipy-0.14.0-cp34-cp34m-macosx_10_6_intel.whl
Traceback (most recent call last):
File "/Users/mb312/.virtualenvs/delocate/bin/delocate-wheel", line 77, in <module>
    main()
File "/Users/mb312/.virtualenvs/delocate/bin/delocate-wheel", line 69, in main
    check_verbose=opts.verbose)
File "/Users/mb312/.virtualenvs/delocate/lib/python2.7/site-packages/delocate/delocating.py", line 477, in delocate_wheel
    "Some missing architectures in wheel")
delocate.delocating.DelocationError: Some missing architectures in wheel

The “intel” argument requires dual architecture extensions and libraries. You can see which extensions are at fault by adding the -v (verbose) flag:

$ delocate-wheel -w fixed_wheels --require-archs=intel -v scipy-0.14.0-cp34-cp34m-macosx_10_6_intel.whl
Fixing: scipy-0.14.0-cp34-cp34m-macosx_10_6_intel.whl
Required arch i386 missing from /usr/local/Cellar/gfortran/4.8.2/gfortran/lib/libgfortran.3.dylib
Required arch i386 missing from /usr/local/Cellar/gfortran/4.8.2/gfortran/lib/libquadmath.0.dylib
Required arch i386 missing from scipy/fftpack/_fftpack.so
Required arch i386 missing from scipy/fftpack/convolve.so
Required arch i386 missing from scipy/integrate/_dop.so
...

I need to rebuild this wheel to link with dual-architecture libraries.

Code

See https://github.com/matthew-brett/delocate

Released under the BSD two-clause license - see the file LICENSE in the source distribution.

travis-ci kindly tests the code automatically under Python 2.7, 3.3 and 3.4.

The latest released version is at https://pypi.python.org/pypi/delocate

Support

Please put up issues on the delocate issue tracker.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

delocate-0.5.0.zip (84.8 kB view details)

Uploaded Source

delocate-0.5.0.tar.gz (62.9 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

delocate-0.5.0-py33-none-any.whl (75.5 kB view details)

Uploaded Python 3.3

delocate-0.5.0-py3-none-any.whl (75.5 kB view details)

Uploaded Python 3

delocate-0.5.0-py2-none-any.whl (75.5 kB view details)

Uploaded Python 2

File details

Details for the file delocate-0.5.0.zip.

File metadata

  • Download URL: delocate-0.5.0.zip
  • Upload date:
  • Size: 84.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No

File hashes

Hashes for delocate-0.5.0.zip
Algorithm Hash digest
SHA256 174b5e6e64f2cee7507e053ccfe66546dea556392fbcb5fcc211a6156aa3871d
MD5 deb91d986ec04c8270fa190417742522
BLAKE2b-256 5ad3839a72d6d19ea70ce49ffa4a8aae66b03cf0a804272d2e48df6e1536435c

See more details on using hashes here.

File details

Details for the file delocate-0.5.0.tar.gz.

File metadata

  • Download URL: delocate-0.5.0.tar.gz
  • Upload date:
  • Size: 62.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No

File hashes

Hashes for delocate-0.5.0.tar.gz
Algorithm Hash digest
SHA256 a106d59d8c87e2e2d83d23df5d502903cfa79ec8833dfb514bc2b88228406253
MD5 2f76f72bb9061cf1370698fe5ac75f65
BLAKE2b-256 a2f40fe21b485926e94a9a4b81e79633e5060e6f2c62f9ba9d898c177dc9ec2e

See more details on using hashes here.

File details

Details for the file delocate-0.5.0-py33-none-any.whl.

File metadata

File hashes

Hashes for delocate-0.5.0-py33-none-any.whl
Algorithm Hash digest
SHA256 4f978506d646a5ad8b3ba630d0da2984e576b5a235266028c6e39d4dfcd64fb5
MD5 8d620cf2959a96147b0ab534e2080cf1
BLAKE2b-256 cd8b744088542b986da0bfe0701ce87a720017441257a89d02c26584b019179d

See more details on using hashes here.

File details

Details for the file delocate-0.5.0-py3-none-any.whl.

File metadata

File hashes

Hashes for delocate-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 dbb93d3c5f25385cda0d2b3200d1c6f6e5651f099cf855d5672900581a56152c
MD5 1f94e9103356c0395e4e23fb9555c19c
BLAKE2b-256 f40cb6035223d7d42958edd19a6643b953ee80df901a24e1c9250b7466630d3b

See more details on using hashes here.

File details

Details for the file delocate-0.5.0-py2-none-any.whl.

File metadata

File hashes

Hashes for delocate-0.5.0-py2-none-any.whl
Algorithm Hash digest
SHA256 f699b52ccbf4f4cc403e94dc3152a77af4fcef4d7f2be9197b7b02192eb5b36d
MD5 ec8545369084f3bcbf22e1c4246f6a19
BLAKE2b-256 7b62a1530dc5f399482c8c98d9690a060d9e1cf2400db3bab8b7834d65e6f332

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page