How to configure CMake/CMakeLists.txt to link generic shared library filename rather than the specific one

792 views Asked by At

I have an application configured using CMake and build with GCC. I'm building on one Linux system and try to run it on another. Unfortunately both systems supply different versions of the same lib. For example GLEW, so whenever I try to run executable on the second system I'm getting this:

./app
./app: error while loading shared libraries: libGLEW.so.2.0: cannot open shared object file: No such file or directory

Here are relevant outputs of app reference and what I have in my system.

ldd ./app | awk '{print $1}' | grep GLEW
libGLEW.so.2.0
ldconfig -p | grep GLEW
        libGLEW.so.2.2 (libc6,x86-64) => /usr/lib/libGLEW.so.2.2
        libGLEW.so.2.2 (ELF) => /usr/lib32/libGLEW.so.2.2
        libGLEW.so.2.1 (libc6,x86-64) => /usr/lib/libGLEW.so.2.1
        libGLEW.so (libc6,x86-64) => /usr/lib/libGLEW.so
        libGLEW.so (ELF) => /usr/lib32/libGLEW.so

I actually would like to configure CMake or whatever to reference the "least common denominator" filename, so instead of libGLEW.so.2.0 it should ref to libGLEW.so

[EDIT] Some additional outputs from the builder OS:

cat CMakeCache.txt  | grep GLEW
...
GLEW_LIBRARIES:FILEPATH=/usr/lib/x86_64-linux-gnu/libGLEW.so
...

ls -al /usr/lib/x86_64-linux-gnu/libGLEW.so
lrwxrwxrwx 1 root root 16 Jan 12  2019 /usr/lib/x86_64-linux-gnu/libGLEW.so -> libGLEW.so.2.1.0

So basically CMake gets it right, but then the GCC linker follows the link and actually places a version specific filename as a reference.

3

There are 3 answers

2
Anonymous1847 On

In this case I would instruct cmake to link against the shared library generic name, which should be libGLEW.so or similar and be a symbolic link to a specific version of the library. Check in /usr/lib. If it does not exist on the build machine or the execution machine, you may need to create it. However, note that there may not be binary compatibility between two versions of libGLEW, as @AlanBirtles pointed out.

1
AudioBubble On

As of cmake 3.15 there is now a cmake module to find glew and handle this better.

Here is a link to the module: https://cmake.org/cmake/help/latest/module/FindGLEW.html?highlight=glew

You should be able to figure it out from there.

0
lhog On

For now I have converged on using patchelf. The solution is based on How can I change the filename of a shared library after building a program that depends on it?

  1. Install patchelf on your linux build host. In my case it's ubuntu, so apt-get install -y patchelf
  2. Check the app dependencies: patchelf --print-needed ./app, which in my case yields:
libSDL2-2.0.so.0
libpthread.so.0
libGL.so.1
libGLU.so.1
libGLEW.so.2.1
libfontconfig.so.1
libfreetype.so.6
libXcursor.so.1
libX11.so.6
libdl.so.2
libIL.so.1
libminizip.so.1
libz.so.1
libunwind.so.8
libvorbisfile.so.3
libopenal.so.1
libcurl.so.4
libstdc++.so.6
libm.so.6
libgcc_s.so.1
libc.so.6
  1. Next replace the links to all missing libraries. In my case it was only libGLEW.so.2.1, so patchelf --replace-needed libGLEW.so.2.1 libGLEW.so ./app Now re-verify of the list of linked libs: patchelf --print-needed ./app
libSDL2-2.0.so.0
libpthread.so.0
libGL.so.1
libGLU.so.1
libGLEW.so
libfontconfig.so.1
libfreetype.so.6
libXcursor.so.1
libX11.so.6
libdl.so.2
libIL.so.1
libminizip.so.1
libz.so.1
libunwind.so.8
libvorbisfile.so.3
libopenal.so.1
libcurl.so.4
libstdc++.so.6
libm.so.6
libgcc_s.so.1
libc.so.6

Note libGLEW.so.2.1 got changed into libGLEW.so

P.S. I don't consider this a proper solution, so any suggestions how to handle linking properly in the first place are more than welcome.