ld cannot find an existing library - linux

I am attempting to link an application with g++ on this Debian lenny system. ld is complaining it cannot find specified libraries. The specific example here is ImageMagick, but I am having similar problems with a few other libraries too.
I am calling the linker with:
g++ -w (..lots of .o files/include directories/etc..) \
-L/usr/lib -lmagic
ld complains:
/usr/bin/ld: cannot find -lmagic
However, libmagic exists:
$ locate libmagic.so
/usr/lib/libmagic.so.1
/usr/lib/libmagic.so.1.0.0
$ ls -all /usr/lib/libmagic.so.1*
lrwxrwxrwx 1 root root 17 2008-12-01 03:52 /usr/lib/libmagic.so.1 -> libmagic.so.1.0.0
-rwxrwxrwx 1 root root 84664 2008-09-09 00:05 /usr/lib/libmagic.so.1.0.0
$ ldd /usr/lib/libmagic.so.1.0.0
linux-gate.so.1 => (0xb7f85000)
libz.so.1 => /usr/lib/libz.so.1 (0xb7f51000)
libc.so.6 => /lib/i686/cmov/libc.so.6 (0xb7df6000)
/lib/ld-linux.so.2 (0xb7f86000)
$ sudo ldconfig -v | grep "libmagic"
libmagic.so.1 -> libmagic.so.1.0.0
How do I diagnose this problem further, and what could be wrong? Am I doing something completely stupid?

The problem is the linker is looking for libmagic.so but you only have libmagic.so.1
A quick hack is to symlink libmagic.so.1 to libmagic.so

As just formulated by grepsedawk, the answer lies in the -l option of g++, calling ld. If you look at the man page of this command, you can either do:
g++ -l:libmagic.so.1 [...]
or: g++ -lmagic [...] , if you have a symlink named libmagic.so in your libs path

It is Debian convention to separate shared libraries into their runtime components (libmagic1: /usr/lib/libmagic.so.1 → libmagic.so.1.0.0) and their development components (libmagic-dev: /usr/lib/libmagic.so → …).
Because the library's soname is libmagic.so.1, that's the string that gets embedded into the executable so that's the file that is loaded when the executable is run.
However, because the library is specified as -lmagic to the linker, it looks for libmagic.so, which is why it is needed for development.
See Diego E. Pettenò: Linkers and names for details on how this all works on Linux.
In short, you should apt-get install libmagic-dev. This will not only give you libmagic.so but also other files necessary for compiling like /usr/include/magic.h.

In Ubuntu, you can install libtool which resolves the libraries automatically.
$ sudo apt-get install libtool
This resolved a problem with ltdl for me, which had been installed as libltdl.so.7 and wasn't found as simply -lltdl in the make.

As mentioned above the linker is looking for libmagic.so, but you only have libmagic.so.1.
To solve this problem just perform an update cache.
ldconfig -v
To verify you can run:
$ ldconfig -p | grep libmagic

Unless I'm badly mistaken libmagic or -lmagic is not the same library as ImageMagick. You state that you want ImageMagick.
ImageMagick comes with a utility to supply all appropriate options to the compiler.
Ex:
g++ program.cpp `Magick++-config --cppflags --cxxflags --ldflags --libs` -o "prog"

Installing libgl1-mesa-dev from the Ubuntu repo resolved this problem for me.

I tried all solutions mentioned above but none of them solved my issue but finally I solved it with the following command.
sudo apt-get install libgmp3-dev
This will do the magic.

Another way to solve this problem is to install the -devel package.
If the compiler is looking for libabc.so while you have libabc.so.1, you need to install the -devel package like libabc-devel as libabc.so.1 is a runtime lib but libabc.so is a development lib.

Related

Q: /usr/bin/ld: cannot find -lGL

The loader gives me this error. I am running Ubuntu 15.04.
When I do: find /usr -type f -name "libGL*"
I get :
/usr/lib/nvidia-352/libGLESv1_CM.so.352.63
/usr/lib/nvidia-352/libGLESv2.so.352.63
/usr/lib/nvidia-352/libGL.so.352.63
/usr/lib/x86_64-linux-gnu/libGLU.so.1.3.1
/usr/lib/x86_64-linux-gnu/libGLEWmx.so.1.10.0
/usr/lib/x86_64-linux-gnu/mesa/libGL.so.1.2.0
/usr/lib/x86_64-linux-gnu/libGLEW.so.1.10.0
/usr/lib32/nvidia-352/libGL.la
/usr/lib32/nvidia-352/libGLESv1_CM.so.352.63
/usr/lib32/nvidia-352/libGLESv2.so.352.63
/usr/lib32/nvidia-352/libGL.so.352.63
So, if i know which is the right one, I can include it by -L"thatfile"
How can i tell which is the right one ? Thanks
Depending on whether you want to link a 32 or 64-bit executable you need /usr/lib32/nvidia-352/libGL.so.352.63 or /usr/lib/nvidia-352/libGL.so.352.63. When the linker does not find -lGL, it is looking for libGL.a or libGL.so..
Also, you need to specify only the directory with -L, like -L/usr/lib/nvidia-352.
Finally, even though this way you can link, at runtime the library still won't be found, unless you set LD_LIBRARY_PATH before you run the executable, or if you add -Wl,-rpath,/usr/lib/nvidia-352, too, to the link command (this latter will embed the path into the executable).
/usr/bin/ld: cannot find -lGL
#user85392, the installed GL is the run time files only. For compiling and linking, the development files are required : Libraries and headers → →
$ sudo apt-get update && sudo apt-get install libgl1-mesa-dev libglu1-mesa-dev

Compiler can't find libxml/parser.h

I am on Debian 8 (Jessie), 64 Bit. I installed libxml2-dev, which now sits in /usr/include/libxml2/libxml.
But when I do (just like libxml docs say)
#include <libxml/parser.h>
I only get when compiling (with gcc)
fatal error: libxml/parser.h: no such file or directory
Notes: On another machine, with an old 64 Bit Suse, where libxml2-dev sits in the exact same path and no other environment vars are set compared to the new Debian, it works perfectly fine. Problem occured while migrating from one to another computer using the exact same makefiles. All other -dev libs that I need just worked (with their documented #include <path>) after the migration (they were all installed with apt-get), only libxml2-dev is not found on compilation.
Do I need to do anything else to make libxml2-dev visible?
if you installed it: sudo apt-get install libxml2-dev libxml2-doc go into /usr/include/libxml2 and copy or move all content from that folder on a level below: cp -R libxml/ ../ After this for me it works.
Try to compile with explicite inclusion where the parser.h file is, i.e. smth like this
g++ -I/usr/include/libxml2/
Following environment variables can also be used for lookup of header files
CPATH
C_INCLUDE_PATH
CPLUS_INCLUDE_PATH
OBJC_INCLUDE_PATH
Find more information here
I came across this same problem on a Centos system. I resolved it by doing the following:
yum install libxml2-devel
cd /usr/include
ln -s libxml2/libxml .
That was it. No change to environment variables or compiler switches.
You should use pkg-config to pass parameters to compiler. Like this
g++ `pkg-config --cflags libxml-2.0` example.c -o example.o
and to linker:
g++ `pkg-config --libs libxml-2.0` example.o -o example

Build OpenSSL with RPATH?

I have Ubuntu 14.04. It came with openssl 1.0.1f. I want to install another openssl version (1.0.2) and I want to compile it by myself.
I configure it as follows:
LDFLAGS='-Wl,--export-dynamic -L/home/myhome/programs/openssl/i/lib
-L/home/myhome/programs/zlib/i/lib'
CPPFLAGS='-I/home/myhome/programs/openssl/i/include
-I/home/myhome/programs/zlib/i/include'
./config --prefix=/home/myhome/programs/openssl/i \
zlib-dynamic shared --with-zlib-lib=/home/myhome/programs/zlib/i/lib \
--with-zlib-include=/home/myhome/programs/zlib/i/include
make
make install
After install, when i check the binary with ldd openssl, and the result is:
...
libssl.so.1.0.0 => /home/myhome/programs/openssl/i/lib/libssl.so.1.0.0 (0x00007f91138c0000)
libcrypto.so.1.0.0 => /home/myhome/programs/openssl/i/lib/libcrypto.so.1.0.0 (0x00007f9113479000)
...
which looks fine. But when I check ldd libssl.so, the result is:
...
libcrypto.so.1.0.0 => /lib/x86_64-linux-gnu/libcrypto.so.1.0.0 (0x00007fac70930000)
...
It still uses the system version of libcrypto. I tried different ways to
build, but result is always stays the same.
My question is how to configure the build in a way, that it can hardcode all binary and library dependencies of shared libraries without using LD_LIBRARY_PATH, or anything like that.
My question is how to configure the build in a way, that it can hardcode all binary and library dependencies of shared libraries without using LD_LIBRARY_PATH, or anything like that.
OpenSSL supports RPATH's out of the box for BSD targets (but not others). From Configure:
# Unlike other OSes (like Solaris, Linux, Tru64, IRIX) BSD run-time
# linkers (tested OpenBSD, NetBSD and FreeBSD) "demand" RPATH set on
# .so objects. Apparently application RPATH is not global and does
# not apply to .so linked with other .so. Problem manifests itself
# when libssl.so fails to load libcrypto.so. One can argue that we
# should engrave this into Makefile.shared rules or into BSD-* config
# lines above. Meanwhile let's try to be cautious and pass -rpath to
# linker only when --prefix is not /usr.
if ($target =~ /^BSD\-/)
{
$shared_ldflag.=" -Wl,-rpath,\$(LIBRPATH)" if ($prefix !~ m|^/usr[/]*$|);
}
The easiest way to do it for OpenSSL 1.0.2 appears to be add it as a CFLAG:
./config -Wl,-rpath=/usr/local/ssl/lib
The next easiest way to do it for OpenSSL 1.0.2 appears to be add a Configure line and hard code the rpath. For example, I am working on Debian x86_64. So I opened the file Configure in an editor, copied linux-x86_64, named it linux-x86_64-rpath, and made the following change to add the -rpath option:
"linux-x86_64-rpath", "gcc:-m64 -DL_ENDIAN -O3 -Wall -Wl,-rpath=/usr/local/ssl/lib::
-D_REENTRANT::-Wl,-rpath=/usr/local/ssl/lib -ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:
${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64",
Above, fields 2 and 6 were changed. They correspond to $cflag and $ldflag in OpenSSL's builds system.
Then, Configure with the new configuration:
$ ./Configure linux-x86_64-rpath shared no-ssl2 no-ssl3 no-comp \
--openssldir=/usr/local/ssl enable-ec_nistp_64_gcc_128
Finally, after make, verify the settings stuck:
$ readelf -d ./libssl.so | grep -i rpath
0x000000000000000f (RPATH) Library rpath: [/usr/local/ssl/lib]
$ readelf -d ./libcrypto.so | grep -i rpath
0x000000000000000f (RPATH) Library rpath: [/usr/local/ssl/lib]
$ readelf -d ./apps/openssl | grep -i rpath
0x000000000000000f (RPATH) Library rpath: [/usr/local/ssl/lib]
Once you perform make install, then ldd will produce expected results:
$ ldd /usr/local/ssl/lib/libssl.so
linux-vdso.so.1 => (0x00007ffceff6c000)
libcrypto.so.1.0.0 => /usr/local/ssl/lib/libcrypto.so.1.0.0 (0x00007ff5eff96000)
...
$ ldd /usr/local/ssl/bin/openssl
linux-vdso.so.1 => (0x00007ffc30d3a000)
libssl.so.1.0.0 => /usr/local/ssl/lib/libssl.so.1.0.0 (0x00007f9e8372e000)
libcrypto.so.1.0.0 => /usr/local/ssl/lib/libcrypto.so.1.0.0 (0x00007f9e832c0000)
...
OpenSSL has a Compilation and Installation on its wiki. This has now been added to the wiki at Compilation and Installation | Using RPATHs
It's 2019, and OpenSSL might have changed a little, so I'll describe how I solved this, on the odd chance someone else might find it useful (and in case I ever need to figure out this command line argument again for myself).
I wanted to build OpenSSL in a way that would cross-compile (using docker containers, because I'm dealing with freakishly old Linux kernels yet modern compilers), yet provide an install that did not depend upon absolute paths, as would be the case using rpath as I've seen described in jww's answer here.
I found I can run OpenSSL's Configure script in this way to achieve what I want (from a bash prompt):
./Configure linux-x86 zlib shared -Wl,-rpath=\\\$\$ORIGIN/../lib
This causes the generated Makefile to build the executables and the shared objects in a way that makes the loader look for dependencies first in "./../lib" (relative to the location of the executable or the shared object), then in the LD_LIBRARY_PATH, etc. That wacky combination of characters properly gets past the bash command line, the script, and the Makefile combinations to create the -rpath argument according to how the linker requires it ($ORIGIN/../lib).
(Obviously, choose the other options that make sense to you.. the key here is in the -Wl,-rpath=\\\$\$ORIGIN/../lib option).
So, if I called ./Configure with a prefix of '--prefix=/opt/spiffness', and later decided to rename 'spiffness' to 'guttersnipe', everything will still work correctly, since the paths are relative rather than absolute.
I have not tried passing the argument into ./config to see if it works there since my use case was a bit special, but I suspect it would. If I were not attempting to cross-compile with dockerized containers, I would prefer using ./config to ./Configure, as it does a decent enough job of examining the current environment to see what kind of binaries to create.
I hope this is useful.

Ubuntu 12.04: ld cannot find library

I'm trying to compile Caffe (http://caffe.berkeleyvision.org/installation.html) and I get the following errors:
/usr/bin/ld: cannot find -lcblas
/usr/bin/ld: cannot find -latlas
However, I have these libraries installed (libatlas).
My LD_LIBRARY_PATH contains the path /usr/lib/atlas-base and it contains the files libcblas.so and libatlas.so (and some other files as well).
Why ld can't find these libraries?
Thanks.
tl;dr: Caffe makefile looks for libblas.so in /usr/lib. If missing, update-alternatives creates a symbolic link /usr/lib/libblas.so to the location where it is installed. Same applies to libcblas.so. LD_LIBRARY_PATH is for runtime, and doesn't have anything to do with this.
LD_LIBRARY_PATH doesn't really help you when compiling. It only provides directories to look for shared libraries when executing programs that rely on them, after they are compiled. Still, when linking during the compilation, the compiler needs to find these shared libraries, and does so by other means than LD_LIBRARY_PATH.
More to the point: if compiling with gcc or clang, the directories in which to look for libraries to link with are provided using the -L flag, and it does not consider the LD_LIBRARY_PATH environment variable.
Common locations for libblas.so are /usr/lib/atlas-base/ and /usr/lib/libblas/. The Makefile for caffe doesn't do anything particular to try and locate these subdirectories, and relies on these libraries being in the default library directory /usr/lib/. Typically a symbolic link /usr/lib/libblas.so exists, and points to the real location of the shared library. For some reason, this wasn't the case in your initial configuration.
When dealing with multiple alternatives for packages, update-alternatives comes in handy. In the case of libblas.so it let's you easily switch between multiple implementations (libblas, openblas) you might have installed, and does so by changing out the symbolic links.
sudo update-alternatives --config libblas.so created this symbolic link when it was missing, which in turn let the compiler find the shared library, solving your problem. This is indicated by the output of the command:
$ sudo update-alternatives --config libblas.so
There is only one alternative in link group libblas.so (providing /usr/lib/libblas.so): /usr/lib/libblas/libblas.so
Nothing to configure.
Same kind of reasoning applies to libcblas.so.
It turns out I had to run
sudo update-alternatives --config libblas.so
sudo update-alternatives --config liblapack.so
and to select libatlas .
I have no idea why,. If anyone can explain this me I will give him the answer.
Thanks.
sudo apt-get install libatlas-base-dev worked for me, it removed both missing dependencies.
See this thread for additional details https://github.com/BVLC/caffe/issues/559
As an addendum to #Ran's answer, Ubuntu in particular has an odd package structure for what's needed with Caffe. I just came across this post in fixing this same issue on my own machine, and here's some help if others are stuck. (Ubuntu 14.04).
libatlas-dev does NOT have libatlas-base-dev as a dependency! Caffe seems to like the libraries from the latter only. Install it.
Then, run the commands suggested by #Ran and select the libraries from the atlas-base directory under /usr/lib. With just libatlas-dev installed, update-alternatives will have the output at the bottom of #swalog's post, but does not actually link an atlas library that caffe seems to approve of! It needs to be the one from atlas-base. Hope this helps!

gcc has been compiled but there is no gcc binary

I have downloaded gcc-4.1.2 from http://gcc.petsads.us/releases/gcc-4.1.2/gcc-4.1.2.tar.bz2 and built with two commands
./configure
make
Now I can see g++ binary. But there is no gcc binary.
$ ls /opt/gcc-4.1.2/host-x86_64-unknown-linux-gnu/gcc/g++
/opt/gcc-4.1.2/host-x86_64-unknown-linux-gnu/gcc/g++
$ ls /opt/gcc-4.1.2/host-x86_64-unknown-linux-gnu/gcc/gcc
ls: cannot access /opt/gcc-4.1.2/host-x86_64-unknown-linux-gnu/gcc/gcc: No such file or directory
What did I miss?
The gcc binary is called xgcc until it is installed.
did you check whether configure and make went without error?
but less probable: did you run also make install which should install all binaries into appropriate directories?

Resources