I'm trying run a program(Snort) that uses libdnet but it fails to find it and outputs:
snort: error while loading shared libraries: libdnet.1: cannot open
shared object file: No such file or directory
Now I know that I should add the library by running ldconfig and putting path to the library in /etc/ld.so.conf. libdnet is located in /usr/local/lib so I don't have to modify ld.so.conf since it already covers that dirctory. So I ran the following commands and tracing the output, I noticed my library is not being loaded.
ldconfig -v
Apparently ldconfig only loads files that have .so somewhere in their names and libdnet.1 doesn't match the pattern.
I've built libdnet from source and installed it using ./configure; make; make install commands. I'd rather not install it using the package manager unless I have to. What should I do?
EDIT:
It says here that libraries should match the patter lib*.so* but I can't rename the library. I neither made it nor am I using it in my own app: if I rename it it will be loaded but I think Snort is looking for libdnet.1 not libdnet.so.1.
Found the answer here. The Solution was simple: make a copy that matches the pattern.
cp /usr/local/lib/libdnet.1.0.1 /usr/local/lib/libdnet.so.1.0.1
A less preferred alternative:
$ LD_LIBRARY_PATH=/usr/local/lib
$ export LD_LIBRARY_PATH
Related
So I got several shared libraries that I am trying to permanently install on my Ubuntu system but I am having some difficulty with it.
I want to install the libraries and the headers in a separate folder under /usr/local/lib and /usr/local/include (for example a folder named agony) so it would be clean and removing them would just require that I delete those folders. so it looks something like this:
/usr/local/lib/agony/libbtiGPIO.so
/usr/local/lib/agony/libbtiDSP.so
...
/usr/local/include/agony/GPIO.h
/usr/local/include/agony/DSP.h
...
And I added a file here /etc/ld.so.conf.d/agony.conf which include a line describing the path to the library folder:
$ cat /etc/ld.so.conf.d/agony.conf
/usr/local/lib/agony
and I perform sudo ldconfig to update the library database.
So to double check if the library is found I do ldconfig -p | grep bti* and
I see the following result:
$ ldconfig -p | grep bti
...
libbtiGPIO.so (libc6,x86-64) => /usr/local/lib/agony/libbtiGPIO.so
libbtiDSP.so (libc6,x86-64) => /usr/local/lib/agony/libbtiDSP.so
...
At this point I should be able to use the libraries without specifying the library path. But When I attempt to compile an application without providing the library path (-L) it fails. However, when I supply gcc with the library path ex:
gcc source.c -L /usr/local/lib/agony output -lbtiGPIO -lbtiDSP
it works!!
I don't want to use LD_LIBRARY_PATH environment variable because this library is going to be used everywhere on the system and I don't want other compilers to worry about providing LD_LIBRARY_PATH.
What am I doing wrong here?
At this point I should be able to use the libraries without specifying the library path
Here lies the confusion.
You have built your shared library libbtiGPIO.so (just sticking with that one),
placed it in /usr/local/lib/agony, and updated the ldconfig database accordingly.
The effect of that is when you run a program that has been linked with libbtiGPIO
then the dynamic linker (/lib/x86_64-linux-gnu/ld-2.21.so, or similar) will know where to look
to load that library into the process and you will not need to tell it by setting an LD_LIBRARY_PATH in the environment.
However, you haven't done anything that affects the list of default library
search directories that are hardwired into your build of gcc, that it passes to
the linker (/usr/bin/ld) when you link a program with libbtiGPIO in the first place.
That list of default search directories is what you will find if your do a verbose
build of your program - gcc -v ... - and then pick out the value of LIBRARY_PATH
from the output, e.g.
LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/5/:\
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/:\
/usr/lib/gcc/x86_64-linux-gnu/5/../../../../lib/:\
/lib/x86_64-linux-gnu/:\
/lib/../lib/:\
/usr/lib/x86_64-linux-gnu/:\
/usr/lib/../lib/:\
/usr/lib/gcc/x86_64-linux-gnu/5/../../../:\
/lib/:\
/usr/lib
/usr/local/lib/agony is not one of those and to make it one of those you
would have to build gcc from source yourself. Hence, in order to link your
program with libbtiGPIO you still need to tell ld where to find it with
-L/usr/local/lib/agony -lbtiGPIO.
man, you misunderstand the procedure of complier and link.
First, libbtiGPIO.so is a shared link library not a static link library. it is important to know those difference .
Then you need to know something else. changing ld.so.conf.d/*.conf and run sudo ldconfig, it affects the procedure of link. in other words, if you don't add agony.conf and sudo ldconfig, you will receive a error when you run ./a.out rather than gcc source.c -L ...., the gcc command can run successfully even thougth you don't ldconfig.
Finally,if you don't pollute the LD_LIBRARY_PATH environment variable, you have to add -L ... options in your gcc command. What'more, if you don't want to input too many words in your shell frequently, you can learn to use Makefile.
So I've edited my /etc/ld.so.conf file and now it looks like this:
include /opt/intel/mkl/lib/intel64_lin
include /etc/ld.so.conf.d/*.conf
include /usr/local/lib
I've tried running sudo ldconfig -v, but in the output it does not seem to even attempt to load the MKL library directory. When I try to run a program using MKL it fails. However, if I add a symbolic link to the correct library in /usr/local/lib which gets added from /etc/ld.so.conf.d/libc.conf it works. Obviously this is an easy solution, but I'm trying to understand why my ldconfig fails?
You have to add library or directory itself:
/full/Path/to/library.so/or/directory to /etc/ld.so.conf file
You must remove include word before directory in your config file.
From man ldconfig:
The ldconfig utility is used to prepare a set of ``hints'' for use
by the
dynamic linker to facilitate quick lookup of shared libraries available
in multiple directories.
<...>
Files named on the command line are expected to contain directories to
scan for shared libraries. Each directory's pathname must start on a new
line. Blank lines and lines starting with the comment character `#' are
ignored. Filenames must conform to the lib*.so.[0-9] pattern in order to
be added to the hints file.
I'm using a node module png which use libpng. After installing libpng, I find some libs in /usr/local/lib. I require the png module:
var png = require('png')
It complained that libpng16.so could not be found.
Error: libpng16.so.16: cannot open shared object file: No such file or directory
But libpng16.so.16 does exist in /usr/local/lib. Then I copy all libpng* to /usr/lib and run code above again, no error for this time!
My question: how could I let Node search libs in /usr/local/lib?
Thanks!
This is a Linux "installing libraries" issue, not a node.js issue (I was confused by the same thing & landed here looking for ideas).
make install will typically copy the library to /usr/local/lib and output some boilerplate suggesting that you modify LD_LIBRARY_PATH or update the ld config. But it doesn't do this for you.
(One thing that can make this more confusing is that the compiler toolchain will search /usr/local by default, so any dependent libraries will compile/link fine.)
Running ldconfig (/sbin/ldconfig) as root or with sudo will update the run-time linker cache, and fix the problem. If not, check that at least one of /etc/ld.so.conf or any of the files in /etc/ld.so.conf.d/ contains the line '/usr/local/lib'.
For more information, run man ldconfig
The problem I faced has been solved here:
Loading shared library in open-mpi/ mpi-run
I know not how, setting LD_LIBRARY_PATH or specifying -x LD_LIBRARY_PATH fixes the problem, when my installation itself specifies the necessary -L arguments. My installation is in ~/mpi/
I have also included my compile-link configs.
$ mpic++ -showme:version
mpic++: Open MPI 1.6.3 (Language: C++)
$ mpic++ -showme
g++ -I/home/vigneshwaren/mpi/include -pthread -L/home/vigneshwaren/mpi/lib
-lmpi_cxx -lmpi -ldl -lm -Wl,--export-dynamic -lrt -lnsl -lutil -lm -ldl
$ mpic++ -showme:libdirs
/home/vigneshwaren/mpi/lib
$ mpic++ -showme:libs
mpi_cxx mpi dl m rt nsl util m dl % Notice mpi_cxx here %
When I compiled with mpic++ <file> and ran with mpirun a.out I got a (shared library) linker error
error while loading shared libraries: libmpi_cxx.so.1:
cannot open shared object file: No such file or directory
The error has been fixed by setting LD_LIBRARY_PATH. The question is how and why? What am i missing? Why is LD_LIBRARY_PATH required when my installation looks just fine.
libdl, libm, librt, libnsl and libutil are all essential system-wide libraries and they come as part of the very basic OS installation. libmpi and libmpi_cxx are part of the Open MPI installation and in your case are located in a non-standard location that must be explicitly included in the linker search path LD_LIBRARY_PATH.
It is possible to modify the configuration of the Open MPI compiler wrappers and make them pass the -rpath option to the linker. -rpath takes a library path and appends its to a list, stored inside the executable file, which tells the runtime link editor (a.k.a. the dynamic linker) where to search for libraries before it consults the LD_LIBRARY_PATH variable. For example, in your case the following option would suffice:
-Wl,-rpath,/home/vigneshwaren/mpi/lib
This would embed the path to the Open MPI libraries inside the executable and it would not matter if that path is part of LD_LIBRARY_PATH at run time or not.
To make the corresponding wrapper add that option to the list of compiler flags, you would have to modify the mpiXX-wrapper-data.txt file (where XX is cc, c++, CC, f90, etc.), located in mpi/share/openmpi/. For example, to make mpicc pass the option, you would have to modify /home/vigneshwaren/mpi/share/openmpi/mpicc-wrapper-data.txt and add the following to the line that starts with linker_flags=:
linker_flags= ... -Wl,-rpath,${prefix}/lib
${prefix} is automatically expanded by the wrapper to the current Open MPI installation path.
In my case, I just simply appends
export LD_LIBRARY_PATH=/PATH_TO_openmpi-version/lib:$LD_LIBRARY_PATH
For example
export LD_LIBRARY_PATH=/usr/local/openmpi-1.8.1/lib:$LD_LIBRARY_PATH
into $HOME/.bashrc file and then source it to active again source $HOME/.bashrc.
I installed mpich 3.2 using the following command on Ubuntu.
sudo apt-get install mpich
When I tried to run the mpi process using mpiexec, I got the same error.
/home/node1/examples/.libs/lt-cpi: error while loading shared libraries: libmpi.so.0: cannot open shared object file: No such file or directory
Configuring LD_LIBRARY_PATH didn't fix my problem.
I did a search for the file 'libmpi.so.0' on my machine but couldn't find it. Took me some time to figure out that 'libmpi.so.0' file is named as 'libmpi.so' on my machine. So I renamed it to 'libmpi.so.0'.
It solved my problem!
If you are having the same problem and you installed the library through apt-get, then do the following.
The file 'libmpi.so' should be in the location '/usr/lib/'. Rename the file to 'libmpi.so.0'
mv /usr/lib/libmpi.so /usr/lib/libmpi.so.0
After that MPI jobs should run without any problem.
If 'libmpi.so' is not found in '/usr/lib', you can get its location using the following command.
whereis libmpi.so
first, run this command
$ sudo apt-get install libcr-dev
if still have this problem then configure LD_LIBRARY_PATH like this:
export LD_LIBRARY_PATH=/usr/local/mpich-3.2.1/lib:$LD_LIBRARY_PATH
then add it to ~/.bashrc before this line:
[ -z "$PS1" ] && return
Simply running
$ ldconfig
appears to me as a better way to solve the problem (taken from a comment on this question). In particular, since it avoids misuse of the LD_LIBRARY_PATH environment variable. See here and here, for why I believe it's misused to solve the problem at hand.
I am following the explanation in this page and this page trying to build and use shared libraries on Ubuntu Linux.
I am building the libraries and application using a cross-compiler on my PC, than copying the files to the target system and running there.
Finally, I am at the stage where all symlinks are defined correctly and the I am able to run the application - but not in the required form.
Let's say that I have a shared library libtest.so.1.0 in a directory /home/ysap/libs. I then created the symlinks libtest.so.1 and libtest.so in the same directory, both pointing to the library file.
In the directory /home/ysap/apps I have an application program app.e that uses the test library.
Now, to run the application, I can type:
> LD_LIBRARY_PATH=/home/ysap/libs ./app.e
and the application runs nicely. However, I'd like to eliminate the assignment, so I tried typing:
> export LD_LIBRARY_PATH=/home/ysap/libs
> ./app.e
but unfortunately I get an error message, saying:
./app.e: error while loading shared libraries: libtest.so.1: cannot open shared object file: No such file or directory
I also tried typing:
> ldconfig -n /home/ysap/libs
and
> sudo ldconfig -n /home/ysap/libs
but it does not help.
What am I doing wrong? How can I make app.e run w/o the variable assignment?
Update 1:
The application uses the mmap() call, so it has to be run with sudo priviledge. The actual invocation line is:
> sudo LD_LIBRARY_PATH=/home/ysap/libs ./app.e
Is it possible that the export-ed variable is not updated in the sudo environment?
Update 2:
Output of ldd ./app.e:
libtest.so.1 => /home/ysap/libs/libtest.so.1 (0xb6faa000)
libgcc_s.so.1 => /lib/arm-linux-gnueabi/libgcc_s.so.1 (0xb6f85000)
libc.so.6 => /lib/arm-linux-gnueabi/libc.so.6 (0xb6ea4000)
/lib/ld-linux.so.3 (0xb6fb7000)
The sudo problem is as #duskwuff states, but if you want to compile an application, and not need to modify the LD_LIBRARY_PATH variable, when linking the application you can use the $ORIGIN variable, which is recognized by most recent versions of linux.
If all the libraries are in the current directory, then when you link the application, you use the extra option:
-Wl,-R'$ORIGIN'
You need to quote the option to prevent it being expanded by the shell when compiling.
If you're putting it into a Makefile then you use:
-Wl,-R\$$ORIGIN
the $$ is for make to use a $, the \ is to prevent the shell that is invoked from the command line expanding the variable before passing it into the command.
You can use any symbolic path reference, so if you had a structure where binaries were in bin/ and libraries were in lib/, you can use $ORIGIN/../lib.
This works for dlopen as well, so it will find libraries when they are being dynamically loaded at run-time
Loading libraries from a user-specified path is a security risk, so sudo always strips out all LD_ environment variables, including LD_LIBRARY_PATH.