python-igraph icon indicating copy to clipboard operation
python-igraph copied to clipboard

Importing error after install on Mac High Sierra

Open mkazanov opened this issue 3 years ago • 16 comments

I am on Mac OS High Sierra (10.13)

After installing igraph I have the following error:

>>> import igraph
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.8/site-packages/igraph/__init__.py", line 26, in <module>
    from igraph._igraph import (
ImportError: dlopen(/usr/local/lib/python3.8/site-packages/igraph/_igraph.cpython-38-darwin.so, 2): Symbol not found: ____chkstk_darwin
  Referenced from: /usr/local/lib/python3.8/site-packages/igraph/.dylibs/libomp.dylib (which was built for Mac OS X 10.15)
  Expected in: /usr/lib/libSystem.B.dylib
 in /usr/local/lib/python3.8/site-packages/igraph/.dylibs/libomp.dylib

mkazanov avatar Jun 17 '22 03:06 mkazanov

@mkazanov Where did you get igraph from? Is there any reason you can't upgrade to macOS 10.14 or later?


@ntamas You might find this helpful:

  • I tested that the PyPI version works on macOS 10.14.6, despite being build for 10.15. 10.14 is a milestone version that many people use, including myself. 10.15 broke compatibility with many older applications and removed 32-bit support entirely.
  • Wheels are built on 10.15 but it is possible to build them for compatibility with older versions. You need to set the environment variable MACOSX_DEPLOYMENT_TARGET to the target version and Clang will pick it up. CMake will pick it up as well and do the right thing. With IGraph/M I target macOS 10.9, which is the oldest version that still supports C++11. However, all dependencies need to be built this way, which means either rebuilding libomp or dropping OpenMP support. In the end, this might be more than what we can reasonably do.

We should formulate a policy on legacy OS support.


@mkazanov macOS 10.13 has been unsupported by Apple since Dec 2020, and 10.14 since Dec 2021. If you are using such an old version you are bound to run into incompatibilities. Even Homebrew itself does not support anything older than 10.15, which impacts other projects' ability to provide legacy support. If you need to use this very old system, I suggest you take a look at MacPorts, which provides very good legacy support and includes python-igraph.

szhorvat avatar Jun 17 '22 09:06 szhorvat

One thing that I don't understand is that the wheels built in the CI environment seem to target macOS 10.9 (judging from the filename). I was under the impression that cibuildwheel sets the deployment target automatically and that's how the generated wheels end up with the macosx_10_9 suffix. Maybe what happens is that the wheel itself is built for macOS 10.9 but not the C core of igraph. I need to investigate this more thoroughly.

ntamas avatar Jun 17 '22 15:06 ntamas

@mkazanov Where did you get igraph from? Is there any reason you can't upgrade to macOS 10.14 or later?

I have the 2017-Mac Book Pro and upgrading to later macOS will results in slowing of all application. I have thousands of software packages on my computer and everything is working except for this package.

Will it work if I compile igraph from source?

mkazanov avatar Jun 17 '22 15:06 mkazanov

I think it should work, but if you don't want to compile but you can wait a day or two, I'll adjust the CI setup and you'll be able to download the pre-built wheels from Github Actions. I'll keep you posted.

ntamas avatar Jun 17 '22 15:06 ntamas

I think it should work, but if you don't want to compile but you can wait a day or two, I'll adjust the CI setup and you'll be able to download the pre-built wheels from Github Actions. I'll keep you posted.

Thank you very much!

Meanwhile, I tried to compile from source and got this message

$pkg-config --cflags --libs igraph
Package igraph was not found in the pkg-config search path.
Perhaps you should add the directory containing `igraph.pc'
to the PKG_CONFIG_PATH environment variable
No package 'igraph' found

This is the content of the directory (there is no igraph.pc here):

$ls
LICENSE		PKG-INFO	build		setup.cfg	src		vendor
MANIFEST.in	README.md	scripts		setup.py	tests

mkazanov avatar Jun 17 '22 16:06 mkazanov

After checking out the source, did you run git submodule update --init --recursive? This should have checked out the source code of the C core of the igraph library in vendor/source/igraph, and then running python setup.py install would compile the source code of the C core first into vendor/build/igraph and vendor/install/igraph, and it would pick up the igraph library from there when linking the Python module.

ntamas avatar Jun 17 '22 16:06 ntamas

After checking out the source, did you run git submodule update --init --recursive? This should have checked out the source code of the C core of the igraph library in vendor/source/igraph, and then running python setup.py install would compile the source code of the C core first into vendor/build/igraph and vendor/install/igraph, and it would pick up the igraph library from there when linking the Python module.

I followed this instruction on python-igraph website (below). At what step I need to run git submodule update --init --recursive?

Compiling from source
In general, you will need a working C and C++ compiler, a POSIX-compatible shell environment ([MSYS2](https://www.msys2.org/) on Windows is okay), make, and the development header files for your version of Python. You will also need [libxml2](https://xmlsoft.org/) for GraphML support. libxml2 might have additional dependencies depending on your platform; for instance, you also need zlib1g-dev on Linux; more about these in the platform-specific instructions below.

The source code of the Python interface bundles a matching version of the C core of the igraph library, and this will be linked to the compiled Python interface statically during the build process, so if everything is installed properly, you can simply run the following command even if we provide no matching pre-compiled wheel:

$ pip install igraph
However, if the C core of igraph has already been installed to a location that can be discovered using pkg-config, you can also instruct the setup script to use pkg-config instead of compiling the bundled version with pip will compile and link the extension to the C core that you have installed. First you need to download and extract the source code of the Python interface:

$ pip download --no-deps --no-binary :all: igraph
$ tar -xvvzf igraph-0.9.11.tar.gz
$ cd igraph-0.9.11
Next, make sure that pkg-config can correctly report the compilation flags needed to link to igraph; the following command should list a bunch of compiler and linker flags instead of reporting an error:

$ pkg-config --cflags --libs igraph
Finally, ask the setup script to compile igraph and use pkg-config for the detection of the C core:

$ python setup.py build --use-pkg-config
$ python setup.py install
See the sections below for additional, platform-specific instructions.

mkazanov avatar Jun 17 '22 16:06 mkazanov

Well, the instructions on the homepage say that pip install igraph should work out-of-the-box in general, and the whole rest of that section refers to the case when you want to build python-igraph from source and link to an existing, installed version of the C core that is already on your system and is discoverable with pkg-config. Your case is a bit special because neither of these two apply to you. Plus, I thought that you checked out the source code from Github so that's why I mentioned running git submodule update --init --recursive to make sure that all the submodules of the source code fetched from Github are also downloaded.

If you haven't checked out the source code from Github yet, try the following command instead:

pip install --no-binary :all: igraph

This will ask pip to download igraph from PyPI, but prevents it from using any of the pre-compiled wheels. pip will then download the official tarball from PyPI and run setup.py install from it, which will in turn compile the C core as well, and there is no need to mess around with pkg-config. Make sure that you installed al lthe dependencies for compilation:

sudo apt install build-essential python-dev libxml2 libxml2-dev zlib1g-dev

ntamas avatar Jun 17 '22 16:06 ntamas

If you haven't checked out the source code from Github yet, try the following command instead:

pip install --no-binary :all: igraph

I tried this command, but still have the same error:

$ pip install --no-binary :all: igraph
Requirement already satisfied: igraph in /usr/local/lib/python3.8/site-packages (0.9.11)
Requirement already satisfied: texttable>=1.6.2 in /usr/local/lib/python3.8/site-packages (from igraph) (1.6.4)
$ python
Python 3.8.6 (default, Oct  8 2020, 14:17:19) 
[Clang 10.0.0 (clang-1000.11.45.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import igraph
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.8/site-packages/igraph/__init__.py", line 26, in <module>
    from igraph._igraph import (
ImportError: dlopen(/usr/local/lib/python3.8/site-packages/igraph/_igraph.cpython-38-darwin.so, 2): Symbol not found: ____chkstk_darwin
  Referenced from: /usr/local/lib/python3.8/site-packages/igraph/.dylibs/libomp.dylib (which was built for Mac OS X 10.15)
  Expected in: /usr/lib/libSystem.B.dylib
 in /usr/local/lib/python3.8/site-packages/igraph/.dylibs/libomp.dylib

mkazanov avatar Jun 17 '22 16:06 mkazanov

As the output says:

Requirement already satisfied: igraph in /usr/local/lib/python3.8/site-packages (0.9.11)

You'll need to uninstall the previous version first with pip uninstall igraph -- or you can probably force an upgrade with pip install --no-binary :all: -U igraph.

ntamas avatar Jun 17 '22 16:06 ntamas

Thank you very much! It finally works!

mkazanov avatar Jun 17 '22 17:06 mkazanov

Awesome! In the meantime, I have updated our CI job to use MACOSX_DEPLOYMENT_TARGET=10.9 when compiling the C core. The macOS wheels are already ready but the Linux i686 job is still running and the artifacts are not published until all jobs are done. It would be great if you could test the build artifact of this CI job when it's done to see if it imports things correctly on your Mac. I think it should be done like this:

  1. Download the build artifacts of the job linked above when they are done (there will be an "Artifacts" panel at the bottom of that page).
  2. Unzip the artifacts and ignore all wheels except the ones ending in macosx_10_9_x86_64.whl
  3. Create a Python virtualenv for testing: python3 -m venv igraph-wheel-test
  4. Run igraph-wheel-test/bin/pip install igraph-0.9.11-cpXX-cpXX-macosx_10_9_x86_64.whl -- replace XX with the version number of your Python installation. E.g., if you use Python 3.8, use 38 in place of XX. If you use Python 3.10, use 310.
  5. Run Python from the virtualenv and try importing igraph: igraph-wheel-test/bin/python3 -c 'import igraph'. If it shows no errors, then the wheel works.
  6. Remove the virtualenv: rm -rf igraph-wheel-test

ntamas avatar Jun 17 '22 17:06 ntamas

Didn't read the whole thread but I think what happens is that libomp.dylib is copied over from Homebrew, and is targeting macOS 10.15 (as the error message indicates). Thus even if the rest of igraph is built for 10.9, this one dylib will potentially prevent operation on anything earlier than 10.15. It seems that the fact that it works on 10.14 is a mere accident.

szhorvat avatar Jun 17 '22 21:06 szhorvat

Indeed @szhorvat, that's the problem. I have checked the built wheel manually, and it includes a hidden .dylibs folder that contains a vendored copy of libomp.dylib, taken directly from Homebrew, which is part of the build environment in Github Actions. Since the oldest macOS image that I can use in Github Actions is 10.15, and Homebrew does not offer a way to build dependencies with an older MACOSX_DEPLOYMENT_TARGET, it looks like we must either:

  • build igraph without OpenMP support for macOS if we want to keep on supporting older macOS versions
  • or build igraph for 10.15, but then force cibuildwheel to mark the wheel as a macOS 10.15 wheel, not 10.9 as it is done now

ntamas avatar Jun 19 '22 23:06 ntamas

Another alternative is to build libomp. I tried this locally on my machine, and installed it to a local prefix, then specified that prefix with CMAKE_PREFIX_PATH, and everything worked fine. Sources are here: https://github.com/llvm/llvm-project/releases/tag/llvmorg-14.0.5 Hopefully cibuildwheel would discover the correct libomp.dylib to copy over. Actually, to avoid worrying about this, we could build a static libomp. It seems entirely feasible.

All that said, I don't think that there's that much value in using OpenMP with igraph.

szhorvat avatar Jun 20 '22 03:06 szhorvat

We never actually got to test if the solution to this issue works properly. @mkazanov can you help with this? Please pick the appropriate wheel for your platform from here and let us know whether it works correctly. If you have Python 3.8, you need igraph-0.9.11-cp38-cp38-macosx_10_9_x86_64.whl.

Feedback about this would be very much appreciated.

szhorvat avatar Jul 05 '22 13:07 szhorvat

This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Oct 01 '22 08:10 stale[bot]