google / s2geometry

Computational geometry and spatial indexing on the sphere
http://s2geometry.io/
Apache License 2.0
2.32k stars 308 forks source link

Python swig binding cannot find libs2.so with default build flags on ubuntu #83

Open jwhiting opened 5 years ago

jwhiting commented 5 years ago

On linux (ubuntu, or more specifically the python3 official docker image), the instructions for building and installing the library for use with python (swig) fail when you actually try to import the library, due to the wrong install path for libs2.so.

Steps to reproduce: with Docker, build an image from this dockerfile, which I've based on the repo's official build instructions:

FROM python:3
WORKDIR /usr/src/app
RUN apt-get update
RUN apt-get install -y cmake libgflags-dev libgoogle-glog-dev libgtest-dev libssl-dev swig
RUN git clone https://github.com/google/s2geometry.git
WORKDIR /usr/src/app/s2geometry
RUN mkdir build
WORKDIR /usr/src/app/s2geometry/build
RUN cmake -DWITH_GFLAGS=ON -WITH_GTEST=ON -DGTEST_ROOT=/usr/src/gtest ..
RUN make
RUN make test
RUN make install
WORKDIR /usr/src/app

Build the image and run the container, and try import pywraps2 as s2 and see the error: ImportError: libs2.so: cannot open shared object file: No such file or directory

A possible fix is to add -DCMAKE_INSTALL_PREFIX:PATH=/usr as a flag to cmake in the build steps. Repeating this exact process but with the additional flag to cmake to change the install path does fix the issue, but, it introduces a new issue: the site-packages location is now incorrect, so python cannot find the pywraps2 module itself. Python is looking in /usr/local/lib/python3.7/site-packages for the module but changing the install path for the shared library also moved the module.

It seems the libs2.so file must go in the /usr install path prefix and the pywraps2 module must go in /usr/local. I do not understand why exactly this is, or where best practice should be, so I don't feel confident in doing a pull request to resolve this.

I can resolve it on my own by adding the cmake flag and then updating python's path to look in the right place for the pywraps2 module.

The issue is raised here as well, though the solution presented is not complete (due to the change in site-packages path).

https://stackoverflow.com/questions/45439754/importerror-libs2-so-cannot-open-shared-object-file-no-such-file-or-directory

Thank you

nieltg commented 4 years ago

Hey, I got an error when using pip3 install s2geometry on Mac. Here's how I install it:

$ OPENSSL_ROOT_DIR=/usr/local/opt/openssl pip3 install s2geometry
WARNING: pip is being invoked by an old script wrapper. This will fail in a future version of pip.
Please see https://github.com/pypa/pip/issues/5599 for advice on fixing the underlying issue.
To avoid this problem you can invoke Python with '-m pip' instead of running pip directly.
Defaulting to user installation because normal site-packages is not writeable
Collecting s2geometry
  Using cached s2geometry-0.9.0.tar.gz (1.1 MB)
Building wheels for collected packages: s2geometry
  Building wheel for s2geometry (setup.py) ... done
  Created wheel for s2geometry: filename=s2geometry-0.9.0-cp37-cp37m-macosx_10_14_x86_64.whl size=719699 sha256=fee30d9971b9ca9f84c62714ba0b7a04b8e265c1f0d74879595efbe11f127111
  Stored in directory: /Users/nieltg/Library/Caches/pip/wheels/a3/ee/98/9d0bb31ca469609afc940534e94c3161dd4706b3ddcc20685a
Successfully built s2geometry
Installing collected packages: s2geometry
Successfully installed s2geometry-0.9.0

This is how I executed it:

$ python3
Python 3.7.3 (default, Dec 13 2019, 19:58:14)
[Clang 11.0.0 (clang-1100.0.33.17)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import s2geometry
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/nieltg/Library/Python/3.7/lib/python/site-packages/s2geometry/__init__.py", line 1, in <module>
    from .pywraps2 import *
  File "/Users/nieltg/Library/Python/3.7/lib/python/site-packages/s2geometry/pywraps2.py", line 13, in <module>
    from . import _pywraps2
ImportError: dynamic module does not define module export function (PyInit__pywraps2)

otool -L says that it still uses Python 2 instead of Python 3.

$ otool -L _pywraps2.so
_pywraps2.so:
    /System/Library/Frameworks/Python.framework/Versions/2.7/Python (compatibility version 2.7.0, current version 2.7.16)
    /usr/local/opt/openssl@1.1/lib/libssl.1.1.dylib (compatibility version 1.1.0, current version 1.1.0)
    /usr/local/opt/openssl@1.1/lib/libcrypto.1.1.dylib (compatibility version 1.1.0, current version 1.1.0)
    /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 800.7.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1281.0.0)
jmr commented 4 years ago

128 makes this use python 3.

jmr commented 4 years ago

128 has been merged, you can try at HEAD.