quantumjot / btrack

Bayesian multi-object tracking
https://btrack.readthedocs.io
MIT License
311 stars 50 forks source link

Automate builds using `cibuildwheel` #192

Closed ianhi closed 1 year ago

ianhi commented 1 year ago

Hi,

I've been trying to run this on my universities cluster and with version 0.4.6 and up the following code gives an error:

import btrack
btrack.BayesianTracker(verbose=False)
---------------------------------------------------------------------------
OSError                                   Traceback (most recent call last)
File /net/holy-nfsisilon/ifs/rc_labs/hekstra_lab/people/ianhi/envs/cellpose/lib/python3.10/site-packages/btrack/libwrapper.py:84, in load_library(filename)
     83 try:
---> 84     lib = ctypes.cdll.LoadLibrary(full_lib_file)
     85     logger.info(f"Loaded btrack: {full_lib_file}")

File /net/holy-nfsisilon/ifs/rc_labs/hekstra_lab/people/ianhi/envs/cellpose/lib/python3.10/ctypes/__init__.py:452, in LibraryLoader.LoadLibrary(self, name)
    451 def LoadLibrary(self, name):
--> 452     return self._dlltype(name)

File /net/holy-nfsisilon/ifs/rc_labs/hekstra_lab/people/ianhi/envs/cellpose/lib/python3.10/ctypes/__init__.py:374, in CDLL.__init__(self, name, mode, handle, use_errno, use_last_error, winmode)
    373 if handle is None:
--> 374     self._handle = _dlopen(self._name, mode)
    375 else:

OSError: /lib64/libm.so.6: version `GLIBC_2.29' not found (required by /net/holy-nfsisilon/ifs/rc_labs/hekstra_lab/people/ianhi/envs/cellpose/lib/python3.10/site-packages/btrack/libs/libtracker.so)

During handling of the above exception, another exception occurred:

OSError                                   Traceback (most recent call last)
Cell In[1], line 1
----> 1 import btrack; btrack.BayesianTracker(verbose=False)

File /net/holy-nfsisilon/ifs/rc_labs/hekstra_lab/people/ianhi/envs/cellpose/lib/python3.10/site-packages/btrack/core.py:128, in BayesianTracker.__init__(self, verbose)
    126 # load the library, get an instance of the engine
    127 self._initialised = False
--> 128 self._lib = libwrapper.get_library()
    129 self._engine = self._lib.new_interface(verbose)
    131 if not verbose:

File /net/holy-nfsisilon/ifs/rc_labs/hekstra_lab/people/ianhi/envs/cellpose/lib/python3.10/site-packages/btrack/libwrapper.py:94, in get_library()
     92 def get_library():
     93     """Loads and returns the btrack shared library."""
---> 94     lib = load_library(os.path.join(BTRACK_PATH, "libs", "libtracker"))
     96     # deal with constructors/destructors
     97     lib.new_interface.restype = ctypes.c_void_p

File /net/holy-nfsisilon/ifs/rc_labs/hekstra_lab/people/ianhi/envs/cellpose/lib/python3.10/site-packages/btrack/libwrapper.py:87, in load_library(filename)
     85     logger.info(f"Loaded btrack: {full_lib_file}")
     86 except IOError:
---> 87     raise IOError(f"Cannot load shared library {full_lib_file}")
     89 return lib

OSError: Cannot load shared library /net/holy-nfsisilon/ifs/rc_labs/hekstra_lab/people/ianhi/envs/cellpose/lib/python3.10/site-packages/btrack/libs/libtracker.so

Running ldd --version gives: ldd (GNU libc) 2.17.

I suspect that the easy fix here to allow this library to work on older glibc version is build it as a static library. Specifically from reading around it seems that changing this line: https://github.com/quantumjot/BayesianTracker/blob/9f08f1c0ff21ef2c9c64fc55e084c97ebc7d3e9a/Makefile#L38 to -DBUILD_SHARED_LIB=OFF might do the trick.

If you think this would be a worthwhile solution then I would be happy to make a PR.

ianhi commented 1 year ago

An alternate solution would be change how the c++ is distributed. It seems as though currently you are compiling the libraries on your computer and adding them to git. Instead you could use cibuildwheel to automatically build them for each OS. This would solve the GLIBC issue for me because the current majorly used manylinux is manylinux2014 https://github.com/pypa/manylinux#manylinux which supports CentOS7. The extra benefit here is that versions of what is supported is tied to the standardize source of the manylinux environrments. The downside is that this is would be more work to implement.

ianhi commented 1 year ago

After looking around a bit it seems that building with static comes with some problems and may not be as simple as I'd hoped.

I do still think that switching to cibuildwheel and building OS specific wheels comes with some benefits, but may be decent work. So in the meantime I'm just building it myself on the cluster which seems to work fine.

quantumjot commented 1 year ago

Thanks @ianhi - The cibuildwheel approach looks like an interesting solution. We'll take a look, but you should also feel free to do a PR if you have the energy to tackle it!

ianhi commented 1 year ago

downloading eigen and building the c++ can happen with the CIBW_BEFORE_BUILD optoin: https://cibuildwheel.readthedocs.io/en/stable/options/#examples_10`

quantumjot commented 1 year ago

Related #198

paddyroddy commented 1 year ago

Hi @ianhi, thanks for the idea on cibuildwheels. @p-j-smith and I had a look, and it did indeed prove a bit tricky! For now, we have added #231 which at least builds the binaries in CI so is better than the current workflow. I have raised a new issue in #235 to explain the changes that would be needed to have a better CI using cibuildwheels. If you have any tips/advice, would be great if you could pop it in that issue for now. Cheers 🙏