linking to linux shared libraries - linux

I am trying to install opendkim on amazon linux ec2 instance. When compiling from source I get:
configure: error: no strlcpy/strlcat found
so I installed libbsd from source. once that is installed I can go to the man page of strlcat and strlcpy but I can't access those functions. I verified that the shared libraries are installed. The output of the libbsd install stated to use one of the 4 options:
If you ever happen to want to link against installed libraries in a given directory, LIBDIR, you must either use libtool, and specify the full pathname of the library, or use the `-LLIBDIR' flag during linking and do at least one of the following:
- add LIBDIR to the `LD_LIBRARY_PATH' environment variable
during execution
- add LIBDIR to the `LD_RUN_PATH' environment variable
during linking
- use the `-Wl,-rpath -Wl,LIBDIR' linker flag
- have your system administrator add LIBDIR to `/etc/ld.so.conf'
I ran
export LD_RUN_PATH=/usr/local/lib
export LD_LIBRARY_PATH=/usr/local/lib/
Additionally my /etc/ld.so.conf contains
include ld.so.conf.d/*.conf
and my /etc/ld.so.conf.d/libbsd.conf contains
/usr/local/lib/libbsd
Lastly checking my libbsd library nm -D /usr/local/lib/libbsd.so contains:
000000000000de30 T strlcat
000000000000ded0 T strlcpy
So my questions how do I either, expose strlcat and strlcpy to the command line? Or how to I do the "use the `-Wl,-rpath -Wl,LIBDIR' linker flag" option, or in general what am i doing wrong in linking to shared libraries? Any help is appreciated. Thanks!

So wasn't ever able to link against the libraries but I was able to resolve the dependencies. The binary rpm from centos installed perfectly :
sudo wget http://dl.fedoraproject.org/pub/epel/7/x86_64/l/libbsd-0.6.0-3.el7.x86_64.rpm
sudo yum localinstall ./libbsd-0.6.0-3.el7.x86_64.rpm
sudo wget http://dl.fedoraproject.org/pub/epel/7/x86_64/l/libbsd-devel-0.6.0-3.el7.x86_64.rpm
sudo yum localinstall ./libbsd-devel-0.6.0-3.el7.x86_64.rpm

Related

Rust import PAM C functions

I'm trying to figure out how to write a Linux PAM in Rust and I've started with this repo. When I compile it with --features libpam (which enables #[link(name="pam")] that imports external C functions), the compiler complains:
error: linking with `cc` failed: exit status: 1
...
note: /usr/bin/ld: cannot find -lpam: No such file or directory
Looking around SO, I've realized that the pam library was not found to be linked. However, I just cannot figure out how to either install it (I can find many libpam-something packages, but no libpam) or locate it such that I can indicate to the compiler/linker where to find it.
When I look into other crates that also work with PAM, they all import the C functions using #[link(name="pam")], and none specifies how to make it work.
I'm using Ubuntu 22.04.
The necessary headers for PAM library can be installed on Ubuntu as part of libpam0g-dev package (link for jammy):
sudo apt install libpam0g-dev
Debian package has the same name (so sudo apt-get install libpam0g-dev), CentOS uses pam-devel package for that (sudo yum install pam-devel).
Alternatively, on any platform you can use the source code from github and follow the installation instructions from README.

clang 3.8+ -fopenmp on linux: ld cannot find -lomp

I have installed clang 3.8 from the base repositories for both Debian Jessie and Fedora 24. When I try to compile a simple HelloWorld.cpp test program with clang++, and i pass the -fopenmp flag, in both cases i get the same error:
/usr/bin/ld: cannot find -lomp
clang-3.8: error: linker command failed with exit code 1 (use -v to see invocation)
I see that if I instead pass -fopenmp=libgomp, it works. However, the Clang OpenMP website says that the OpenMP runtime is shipped with Clang 3.8. Why, then, can it not find the default libomp library? I do not see this library anywhere on my system.
There is good chances that the OpenMP development package is missing on your system.
On Ubuntu: sudo apt install libomp-dev
If you have libomp installed correctly you will need to use -fopenmp=libomp. libgomp is for gcc. You might check that clang isn't symbollically linked to gcc on your computer.
TL;DR
If you have libomp.so for llvm in somewhere like /usr/lib/llvm-12/lib make file /etc/ld.so.conf.d/libomp.conf with the line /usr/lib/llvm-12/lib in it, then run sudo ldconfig.
Intro
In my case, I had libomp-12-dev installed, but it was not in my linker's library path. See the footnote on how I found the library. There are a couple solutions in this scenario:
Add library path with ldconfig
If you want this in your default library path, consider using ldconfig [man page].
This will look for files in /etc/ld.so.conf. For me, running Ubuntu 20.04, this file only points to including files in the directory /etc/ld.so.conf.d.
$ cat /etc/ld.so.conf
include /etc/ld.so.conf.d/*.conf
As such, I made a config llvm-libomp-12 in my /etc/ld.so.conf.d directory that looks like this:
$ cat /etc/ld.so.conf.d/libomp.conf
# libomp.so for llvm
/usr/lib/llvm-12/lib
Then I asked ldconfig to update the paths with sudo ldconfig. You can add the -v flag and it will print all libraries and paths it is aware of.
Add library to environment variable
We can also direct the linker to our library using the $LD_LIBRARY_PATH environment variable
This may be advantageous if you're on a multiuser system and don't want to impact others, or if you have temporary changes to your library paths you would like to make in your shell.
See what your current $LD_LIBRARY_PATH is with echo $LD_LIBRARY_PATH. You may not have this set by default. Add paths to this variable, each delimited by a colon.
For your current shell session, simply append or prepend to your $LD_LIBRARY_PATH like this (assuming bash, zsh, or fish >v3.0):
export "$LD_LIBRARY_PATH:/path/to/lib"
Or for a more permanent change limited to your user, add the above export to your shell's config file (e.g. ~/.bashrc).
Manually specify library path(s) in compiler flags
Nice for a one-off specific library that you don't always want in your default library paths. Specify the path to the library as a flag like this:
-L/path/to/lib
For example:
clang++ -L/usr/lib/llvm-12/lib [...]
make -L/usr/lib/llvm-12/lib
Footnotes
On searching
If you don't know where a given library you need is, you can use things like find. Personally though, I used a package called mlocate that indexes files on my machine and allows you to search them.
Installing mlocate
sudo apt install mlocate
Updating the indexes
sudo updatedb
Searching for a substring
locate libomp.so
When I searched for where my libomp libraries were, I did this:
$ locate libomp.so
/usr/lib/llvm-12/lib/libomp.so
/usr/lib/llvm-12/lib/libomp.so.5
/usr/lib/x86_64-linux-gnu/libomp.so.5
Notably it seemed like clang was using the libomp.so.5 in the linux-gnu directory, but I needed it to be using the llvm library.
Environment used in this post
$ lsb_release --all
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 20.04.2 LTS
Release: 20.04
Codename: focal
$ uname -a
Linux bip 5.8.0-48-generic #54~20.04.1-Ubuntu SMP Sat Mar 20 13:40:25 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
TODO
Some notes that could be added to this question:
Confirm and list priority of env vars vs config files vs flags (does this vary between compilers and linkers?)
Ordering library paths when using multiple config files (can we prefix with numbers to ensure the order libraries are parsed?)

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!

ldconfig loading only .so files

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

trying to install hs-ffmpeg haskell package fails to find libdc1394

doing "cabal install hs-ffmpeg" fails like this:
checking for faacEncGetVersion in -lfaac... no
checking for zlibVersion in -lz... yes
checking for libdc1394... configure: error: Package requirements (libdc1394) were not met:
No package 'libdc1394' found
Consider adjusting the PKG_CONFIG_PATH environment variable if you
installed software in a non-standard prefix.
Alternatively, you may set the environment variables libdc1394_CFLAGS
and libdc1394_LIBS to avoid the need to call pkg-config.
See the pkg-config man page for more details.
cabal: Error: some packages failed to install:
hs-ffmpeg-0.3.4 failed during the configure step. The exception was:
exit: ExitFailure 1
I have libdc1394-22 and libdc1394-22-dev installed on Ubuntu 9.10 Karmic Koala.
I'm thinking that the dependency needs to be updated to reflect the new package that supercedes libdc1394, but I'm not sure how to do that.
hs-ffmpeg's configure script is looking for a libdc1394.pc. For some reason, Ubuntu ships a libdc1394-2.pc instead.
Edit hs-ffmpeg's configure.ac to use the "correct" name and then run autoreconf, and it should work.
Something like mkdir -p ~/.pc; ln -s /usr/lib/pkgconfig/libdc1394-2.pc ~/.pc/libdc1394.pc; export PKG_CONFIG_PATH+=:~/.pc may work too.

Resources