/usr/bin/ld: cannot find -lGL (Nvidia, (L)Ubuntu 12.10) - opengl

I'm failing to link against OpenGL in my C++/Qt5 projects. I link using the following command:
g++ -m64 -Wl,[...] -o [...] [...].o \
-L/usr/X11R6/lib64 -L[...]/qt-5.0.0/5.0.0/gcc_64/lib \
-lQt5Widgets -lQt5Network -lQt5Gui -lQt5Core -lGL -lpthread
I hope the [...] aren't hiding something important. If you think they are, please let me know.
I get the following error:
/usr/bin/ld: cannot find -lGL
I'm on an Lubuntu 12.10 system and using Qt5 from http://qt-project.org/downloads. Since the system is newly installed, the first thing I did was installing Ubuntu's nvidia-current package and I rebooted. Among others, the following libraries have been installed on my system:
$ ll /usr/lib/nvidia-current/
[...]
lrwxrwxrwx 1 root root 10 Oct 6 04:58 libGL.so -> libGL.so.1
lrwxrwxrwx 1 root root 15 Oct 6 04:58 libGL.so.1 -> libGL.so.304.43
-rw-r--r-- 1 root root 1076560 Oct 6 04:58 libGL.so.304.43
[...]
I googled on how to add this path to the default library search path, as I guessed that g++ doesn't look in the subfolder nvidia-current but only in /usr/lib. So I added the path to ld.conf.d in Ubuntu. I updated ldconfig and checked with the following command:
$ ldconfig -p | grep libGL.so
libGL.so.1 (libc6,x86-64) => /usr/lib/nvidia-current/libGL.so.1
libGL.so.1 (libc6) => /usr/lib32/nvidia-current/libGL.so.1
libGL.so (libc6,x86-64) => /usr/lib/nvidia-current/libGL.so
libGL.so (libc6) => /usr/lib32/nvidia-current/libGL.so
So everything looks just fine!
Still (even after rebooting), the error from above appears. Am I missing something?
Edit:
After adding -L/usr/lib/nvidia-current/, everything works fine. But it seems that this is not the correct way to link against a library in a default path.

It's common for distributions to install graphics drivers' libGL not into the system library path, but some additional directory in /usr/lib to allow for installing different variants of libGL.so on the same system. Then symlinks to the active libGL.so are created by some centralized configuration system, for example alternatives as used by Ubuntu and Debian. It may very well be, that this configuration step failed.
/usr/lib/nvidia-current is not a standard library path and hence the library is not found; this also should mean, that OpenGL programs should not work. Maybe the Ubuntu folks do something with the LD_LIBRARY_PATH environment variable to circumvent this.
Personally I suggest that you add symlinks, as you should always have libGL.so in the defaul library path, preferrably /usr/lib or on 32/64 bit multilib systems in /usr/lib64 and /usr/lib32
/usr/lib/libGL.so.1 => /usr/lib/nvidia-current/libGL.so.1
/usr/lib32/libGL.so.1 => /usr/lib32/nvidia-current/libGL.so.1
/usr/lib/libGL.so => /usr/lib/nvidia-current/libGL.so
/usr/lib32/libGL.so => /usr/lib32/nvidia-current/libGL.so
You can also do this using the alternatives system, adding a new alternative.

Related

Why linux ld somtime use the symbolic link of libs

I use the jsoncpp lib in my linux cli tool.
The CMakeLists.txt contains
find_library(LIB_JSON jsoncpp)
target_link_libraries(${PROJECT_NAME} ${LIB_JSON})
The result is
/usr/bin/c++ -rdynamic CMakeFiles/cktwagent.dir/agent_main.cpp.o -o cktwagent -ljsoncpp
When i check the binary I found:
$> ldd cktwagent
linux-vdso.so.1 (0x00007ffe4cfd1000)
libjsoncpp.so.24 => /usr/lib/libjsoncpp.so.24 (0x00007f87505bd000)
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00007f87503e0000)
libm.so.6 => /usr/lib/libm.so.6 (0x00007f875029a000)
libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x00007f8750280000)
libc.so.6 => /usr/lib/libc.so.6 (0x00007f87500b7000)
/lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007f87506ce000)
Why ld use /usr/lib/libjsoncpp.so.24 and not the symbolic link /usr/lib/libjsoncpp.so?
Why the ld sometime resolv the linbrary link to the real library file?
$> ls -l /usr/lib/libjsoncpp.so
lrwxrwxrwx 1 root root 16 26. Sep 17:02 /usr/lib/libjsoncpp.so -> libjsoncpp.so.24
In case of /usr/lib/libstdc++.so.6 the ld use the symbolic link. When i check the path from ldd output, libstdc++.so.6 point to a symbolic link.
$> ls -l /usr/lib/libstdc++.so.6
lrwxrwxrwx 1 root root 19 9. Nov 12:43 /usr/lib/libstdc++.so.6 -> libstdc++.so.6.0.28
I like to understand this behavior. Because when i copy the binary to a different system, the link to libjsoncpp.so available. But it points to some different version.
Many thanks
Thomas
That's a version compatibility feature. By convention, API compatibility is determined by the major version number. So 6.0.28 would be is compatible with 6.1.1, but not with 5.0.1 or 7.0.1.
To allow for compatible upgrades, libstdc++.so.6.0.28 is symlinked as libstdc++.so.6. Then it can be binary-upgraded to e.g. libstdc++.so.6.0.29 without touching applications that rely on API version 6 of libstdc++.
In addition, it allows libraries with different major version numbers to coexist on the same system. Installing libstdc++.so.7.0.0 will not break apps that link against libstdc++.so.6.
Why ld use /usr/lib/libjsoncpp.so.24 and not the symbolic link /usr/lib/libjsoncpp.so?
That's because libjsoncpp has a soname of libjsoncpp.so.24. Apparently it is following the same convention of having the major version number determine compatibility.
You can achieve the same behavior with your shared lib libfoo if you link it like this:
gcc -shared -Wl,-soname,libfoo.so.<major> -o libfoo.so.<major>.<minor>
For more details refer to GCC Howto - Version numbering, sonames and symlinks.

ld cannot load library despite symlink existing

I am trying to compile a program that requires SFML 2.41+. Ubuntu 16.04's repos don't have a new enough version so I installed SFML 2.4.2 by following the (somewhat sparse) instructions on this page. Specifically I dowloaded the Linux version from this page, extracted it, dug down until I found the lib, share, and include folders and copied those folders over the folders of the same name in /usr/local/.
When running the included Makefile I get the following errors:
/usr/bin/ld: cannot find -lsfml-system
/usr/bin/ld: cannot find -lsfml-window
/usr/bin/ld: cannot find -lsfml-graphics
Focusing on sfml-system for the moment, if I run ld -lsfml-system --verbose | grep /usr/local/lib I get the following:
attempt to open //usr/local/lib/x86_64-linux-gnu/libsfml-system.so failed
attempt to open //usr/local/lib/x86_64-linux-gnu/libsfml-system.a failed
attempt to open //usr/local/lib/libsfml-system.so failed
attempt to open //usr/local/lib/libsfml-system.a failed
if I run sudo ls -l /usr/local/lib | grep libsfml-system.so I get the following:
lrwxrwxrwx 1 root root 21 Oct 16 01:38 libsfml-system.so -> libsfml-system.so.2.4
lrwxrwxrwx 1 root root 23 Oct 16 01:38 libsfml-system.so.2.4 -> libsfml-system.so.2.4.2
-rw-r--r-- 1 root root 72080 Feb 10 2017 libsfml-system.so.2.4.2
So I appear to have a symlink to a .so file in the path ld is looking in.
Why can't it load the library?
(I was initially concerned about the double slashes, but this question suggests those are okay.)
what i've tried so far
I've now tried running sudo ldconfig and sudo ldconfig /usr/local/lib/. Neither of those have changed the behaviour of ld -lsfml-system
Specifcally when I run sudo ldconfig --verbose 2> /dev/null | grep sfml I get
libsfml-window.so.2.4 -> libsfml-window.so.2.4.2
libsfml-graphics.so.2.4 -> libsfml-graphics.so.2.4.2
libsfml-audio-d.so.2.4 -> libsfml-audio-d.so.2.4.2
libsfml-graphics-d.so.2.4 -> libsfml-graphics-d.so.2.4.2
libsfml-audio.so.2.4 -> libsfml-audio.so.2.4.2
libsfml-window-d.so.2.4 -> libsfml-window-d.so.2.4.2
libsfml-system.so.2.4 -> libsfml-system.so.2.4.2
libsfml-system-d.so.2.4 -> libsfml-system-d.so.2.4.2
libsfml-network-d.so.2.4 -> libsfml-network-d.so.2.4.2
libsfml-network.so.2.4 -> libsfml-network.so.2.4.2
libsfml-network.so.2.3 -> libsfml-network.so.2.3.2
libsfml-graphics.so.2.3 -> libsfml-graphics.so.2.3.2
libsfml-system.so.2.3 -> libsfml-system.so.2.3.2
libsfml-window.so.2.3 -> libsfml-window.so.2.3.2
(On stderr I just get messages that appear to be merely informational,for example:
/sbin/ldconfig.real: Path `/usr/local/lib' given more than once
and
/sbin/ldconfig.real: /lib/i386-linux-gnu/ld-2.23.so is the dynamic linker, ignoring
so I figured they weren't important.)
Since /etc/ld.so.cache was mentioned, I made a copy of it with cp /etc/ld.so.cache /etc/ld.so.cache.bak and re-ran sudo ldconfig. A new cache file was generated but it wasn't any different, that is diff /etc/ld.so.cache /etc/ld.so.cache.bak doesn't print anything.
The problem turned out to be that the permissions on my /usr/local/lib/ got changed when I copied the files over them. Specifically the execute bits seem to have been unset. After setting those again, I can now link those libraries properly!
The standard Linux libraries are cached in /etc/ld.so.cache. If you add libraries to the standard path, you need to also run (as root) ldconfig.

C++ program not linking to .so file properly

I built GLEW (using make install) to use in a small test program I am writing (source can be found here if you need it). I ran locate libGLEW.so just to check if the GLEW libraries were properly installed, and got the following output:
/usr/lib64/libGLEW.so
/usr/lib64/libGLEW.so.2.0
/usr/lib64/libGLEW.so.2.0.0
This was completely normal. I then compiled it using the command:
g++ main.cpp -o main -lglfw -lGLEW -lGL -lX11 -lpthread -lXi -g
This also threw up no errors. However, when I tried to execute the program:
./main: error while loading shared libraries: libGLEW.so.2.0: cannot open shared object file: No such file or directory
Just for a sanity check, I ran ldd main | grep "GLEW", and sure enough:
libGLEW.so.2.0 => not found
I initially thought that this could be a problem with the linker not searching the directory containing the libraries. So I ran the command ld --verbose | grep "/usr/lib64" and there was a SEARCH_DIR containing the required directory:
... SEARCH_DIR("=/usr/lib64"); ...
This was especially confusing. I tried compiling with the -L/usr/lib64 option, but the same error message still persisted. I checked that the symlinks to the library were correct and they were:
lrwxrwxrwx 1 root root 16 Jul 15 10:22 libGLEW.so -> libGLEW.so.2.0.0
lrwxrwxrwx 1 root root 16 Jul 15 10:38 libGLEW.so.2.0 -> libGLEW.so.2.0.0
-rw-r--r-- 1 root root 707K Jul 15 10:22 libGLEW.so.2.0.0
I am not sure what exactly is causing the issue but I'm starting to believe that I didn't install the libraries correctly. I feel like the answer is right in front of my eyes but I can't find it.
Thanks in advance for any help.
Debian and Ubuntu do not install system libraries into /usr/lib64, and the installation instructions you used are wrong for those systems. (It is not a good idea to install libraries bypassing the packaging system into /usr anyway.) /usr/local/lib is searched by default (unlike other systems), so you could move the libraries to that directory.
Compile with -Wl,-rpath=/usr/lib64

When I include a shared library, my executable is looking for two versions of it

When I make my program with -larmadillo, I get an executable which wants two versions of it:
$ ldd ./a.out | grep armadillo
$ libarmadillo.so.7 => /usr/lib/x86_64-linux-gnu/libarmadillo.so.7 (0x00007fd5e29a0000)
$ libarmadillo.so.4 => not found
Can anyone point me in the right direction? This isn't making any sense to me!
Background: I initially installed libarmadillo via sudo apt-get install libarmadillo-dev, then I realised I needed to build it with a specific parameter (64 bit words enabled), so I uninstalled it via sudo apt-get remove libarmadillo-dev then downloaded the latest version, configured and make/make installed it. Presumably I only have one version of libarmadillo on my system - I do not see any old libraries in the usual places.
Thanks
EDIT:
My Makefile is:
CC= g++
CFLAGS= -Lcontrib/armadillo-7.400.1 -L/usr/include -Lcontrib/mlpack-2.0.1/build/lib -fpermissive -std=c++11 -O0 -g -Wall
LDFLAGS= -lmlpack -larmadillo
The verbose output of ldd is interesting, I think?
$ ldd -v ./a.out | grep armadillo
$ libarmadillo.so.7 => /usr/lib/x86_64-linux-gnu/libarmadillo.so.7 (0x00007fd5e29a0000)
$ libarmadillo.so.4 => not found
$ /usr/lib/x86_64-linux-gnu/libarmadillo.so.7:
The latter section (which lists dependences for libarmadillo.so.7) is:
/usr/lib/x86_64-linux-gnu/libarmadillo.so.7:
ld-linux-x86-64.so.2 (GLIBC_2.3) => /lib64/ld-linux-x86-64.so.2
libc.so.6 (GLIBC_2.2.5) => /lib/x86_64-linux-gnu/libc.so.6
There is no mention of the 'missing' libarmadillo.so.4 in the verbose output, which I find quite strange.
I think I've figured it out, but the results aren't particularly comforting.
I reinstalled mlpack which has a dependency into libarmadillo, and then rebuilt, and the requirement for libarmadillo.so.4 is gone.
The process that I think happened is I:
Installed old version of libarmadillo
Installed libmlpack configured with old version
Realised I needed a newer version of libarmadillo, so uninstalled old libarmadillo and installed a new one.
Rebuilt mlpack using cmake / make but did not make install
Made my executable
Now have an executable which is is pointing to mlpack which requires the old libarmadillo, but it also points to the new libarmadillo
Once I make install the rebuilt mlpack, my problems go away. I am surprised that the verbose output of ldd didn't flag any reason as to why it was looking for libarmadillo.so.4 (namely that there was a dependency from libmlpack on the old library) - should ldd be able to do this?
Sometimes linux creates many symbolic link of one dynamic library. I don't know why but no matter as there is no inconvenient for that. So, you can just create a new symbolic link like this : ln -s path_to_my_so_lib/my_lib.so /usr/lib/x86_64-linux-gnu/libarmadillo.so.4

How can one build openssl on ubuntu with a specific version of zlib?

Background
I'd like to build OpenSSL against a specific version of zlib so that all of my code is built by me. I do this for many of the libraries I use so that I don't get different behaviour on different versions of the operating system. I understand that this isn't strictly necessary, but I wanna.
What I've Done
I've built zlib in ~/zlib/zlib-1.2.7, and installed zlib to ~/zlib/lib and ~/zlib/include.
(Note that I've simplified all paths in this post by substituting my working directory for '~')
I've built openssl passing these arguments to ./config
--with-zlib-lib=~/zlib/lib
--with-zlib-include=~/zlib/include
When I build openssl, I can see that the appropriate -I argument is being passed to GCC
./config --prefix=~/openssl --openssldir=openssl/ssl threads zlib-dynamic shared --with-zlib-lib=~/zlib/lib --with-zlib-include=~/zlib/include && make && make install
. . .
...many lines of output...
. . .
gcc -I.. -I../.. -I../modes -I../asn1 -I../evp -I../../include -I/home/ubuntu/zlib/include -fPIC -DOPENSSL_PIC -DZLIB_SHARED -DZLIB -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -Wa,--noexecstack -m64 -DL_ENDIAN -DTERMIO -O3 -Wall -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DMD5_ASM -DAES_ASM -DVPAES_ASM -DBSAES_ASM -DWHIRLPOOL_ASM -DGHASH_ASM -c -o cm_pmeth.o cm_pmeth.c
OpenSSL builds successfully.
The Problem
I check what version of zlib is being linked with the command ldd libssl.so.
ubuntu#lemming012:~/ben/code/optimiser/libs/3rdParty/openssl/lib$ ldd libssl.so
linux-vdso.so.1 => (0x00007fff3e7ff000)
libcrypto.so.1.0.0 => /lib/x86_64-linux-gnu/libcrypto.so.1.0.0 (0x00007f
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f289bcab000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f289baa6000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f289b88f000)
/lib64/ld-linux-x86-64.so.2 (0x00007f289c6c7000)
I expect to see ldd reporting my own libz file in the list.
Instead, ldd reports that libssl is linked to my system installed version of libz. The results are identical if I copy my own version libz.so.1 into the libssl 'lib' directory before running ldd in that same directory.
Question
What have I done wrong? How can I get OpenSSL to link to my version of zlib instead of the version installed on the system?
Environment
uBuntu 13.04 x64
compiling with GCC
building with Make
The answer turns out to be, you need to set an rpath with a syntax similar to the following. I do mine in a Makefile, which is the reason for the double '$'.
LDFLAGS += -Wl,-rpath,'$$ORIGIN/../lib'
Now, I don't necessarily need to do this on the library (openssl) itself. I can do this on the calling executable instead. If the library has no rpath, the rpath on the executable gets used next. In short, I don't need to stress that ldd -r <library> is returning the wrong path, provided that ldd -r <executable> returns the correct path.
I can test by library with the following command:
env LD_LIBRARY_PATH=$PWD ldd -r <library>
And once my executable is compiled, I can verify everything like this:
ldd -r <executable>
Long story short, everything is working just fine, don't get hung up on what ldd -r <library> is returning, just worry about ldd -r <executable>.
./config --prefix=/data/services/openssl-1.0.2g shared zlib -I/data/services/zlib-1.2.7/include -L/data/services/zlib-1.2.7/lib