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

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?)

Related

cannot revise gcc version even after installing the new and deleting the old one

I work on CentOS 5.5 and my computer used gcc-4.1.2 until now, and under /usr/lib/gcc/x86_64-redhat-linux/ there were 2 indexes: 4.1.1 and 4.1.2. For using some softwares I must update the gcc.
But after I installed gcc-4.7.0 from the downloaded gcc-4.7.0.tar.gz (I did not use yum because when I tried it all servers told me that I had the latest version which was certainly not true, and perhaps this was also caused by the problem I now face with), the /usr/lib/gcc/x86_64-redhat-linux/4.7.0/ was created just like the 4.1.1 and 4.1.2 index, so under /usr/lib/gcc/x86_64-redhat-linux/ there were 3 indexes: 4.1.1, 4.1.2 and 4.7.0. And under /usr/lib/gcc/x86_64-redhat-linux/4.7.0/ there were 6 indexes:
bin include lib lib64 libexex share
It looked like that 4.7.0 was successfully installed but when I ran
gcc --version
the result was still
gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-48)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is
NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
I also ran
update-alternatives --install /usr/bin/gcc gcc /usr/lib/gcc/x86_64-redhat-linux/4.7.0 40
to raise the priority of 4.7.0, and when I ran
update-alternatives --config gcc
it said
There is 1 program that provides 'gcc'.
Selection Command
-----------------------------------------------
*+ 1 /usr/lib/gcc/x86_64-redhat-linux/4.7.0
Enter to keep the current selection[+], or type selection number:
And I printed 1, all it looked like that 4.7.0 was selected as the default gcc, but when I ran gcc --version, the result was not changed! Still 4.1.2.
After that I even removed all 4.1.2 gcc and its related programs by rpm -e and deleted the index, but the result of gcc --version became
-bash: gcc: command not found.
It didn’t change when I reinstalled the 4.7.0.
After all, when I looked for the links of /usr/bin/gcc/ I found
/usr/bin/gcc -> /etc/alternatives/gcc
and link of /etc/alternatives/gcc was
/etc/alternatives/gcc -> /usr/lib/gcc/x86_64-redhat-linux/4.7.0
this should be the result of my running the update-alternatives line, so it has worked. It did make the link to 4.7.0. So why didn’t this link call 4.7.0 in the end? I can’t find out.
I even made the direct link to 4.7.0 then:
ln -s /usr/lib/gcc/x86_64-redhat-linux/4.7.0 /usr/bin/gcc
however this still didn’t work.
I am very confused with it. I will be grateful for your help. Thank you very much!
p.s. Thank Basile Starynkevitch very much for noticing me to make these explanations:
I have /usr/bin/ in my PATH, so this should be OK.
I am teached that /usr/bin/gcc/ should be linked to an executable but not index, so the link to 4.7.0 is wrong. But could anyone tell me which executable to link to, or which executable is /usr/bin/ linked to in a common computer? This may very likely lead to the solution to the problem.
I cannot run configure one more time because configure itself requires gcc but now it is not found. So I'm afraid the problem cannot be fixed by that.
Be aware of the PATH variable. You could have some $HOME/bin/ in it.
Restore your system's gcc (so undo all the mess you have done). Then run which gcc and gcc -v to understand what is it exactly.
If you compile GCC from its source code (as distributed by the FSF), choose a recent version, e.g. GCC 8 in fall 2018.
Read carefully about installing GCC. Compile it outside of its source code. Be aware of the many configure options. I suggest to consider configuring it with some --program-suffix option (such as --program-suffix=-8) and then adding symlinks (e.g. $HOME/bin/gcc -> /usr/local/bin/gcc-8) appropriately.
ln -s /usr/lib/gcc/x86_64-redhat-linux/4.7.0 /usr/bin/gcc
it is wrong. Since /usr/lib/gcc/x86_64-redhat-linux/4.7.0/ is some internal directory, and /usr/bin/gcc has to be an executable.
You probably don't need to run update-alternatives, but you do need to add (cleverly) something in a directory mentioned in your PATH
See also this answer to a similar question.
after edits in the question
You need first to clean up the mess you did under /usr/ (in particular in /usr/bin/ which you should never change without your package system). Remove all the things you added under /usr/bin/ and /usr/lib/. Then re-install forcibly and explicitly appropriate system gcc packages (using yum or some other package manager).
I have /usr/bin/ in my PATH, so this should be OK.
Probably not. My recommendation is to have $HOME/bin/ and /usr/local/bin/ early in your PATH (so before /usr/bin/; you might need to edit ~/.bashrc to change your PATH setting) and to add your new gcc, as something like gcc-8 (if you compile GCC 8 from its source code), there. If you want a system wide installation, have some /usr/local/bin/gcc-8 program. If you want a personal installation, have some $HOME/bin/gcc-8 program (both could be absolute symlinks to somewhere else).

shared library not found during compilation

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.

Header files are not found by GCC

Working with embedded C-projects. There are libraries, include files and so on - for micro controllers. No need for me to use GCC for a host machine and OS (Linux Mint 64 bit). As a rule...
But now I'm trying to compile mspdebug project from a Github - with a GCC of course. And I get an error at the very begin of make:
mspdebug$ make
cc -DUSE_READLINE -O1 -Wall -Wno-char-subscripts -ggdb -I. -Isimio -Iformats -Itransport -Idrivers -Iutil -Iui -DLIB_DIR=\"/usr/local/lib/\" -o util/btree.o -c util/btree.c
util/btree.c:19:20: fatal error: assert.h: No such file or directory
#include <assert.h>
^
compilation terminated.
I search for the includes in all possible paths (I've got the list of them via gcc -v command) - there are no assert.h file, as well, as stdio.h and so on. Except virtual box directories there is only one place (where GCC does not search includes): /usr/lib/syslinux/com32/include
AFAIK, all standard libs and includes are installed with the GCC. So I try to reinstall GCC (4.8.4) - nothing changes.
What is the normal way to give GCC all standard environment it needs?
Thanks to the right direction set by Sam Varshavchik I found the info in the stackoverflow. So I did the following:
1) installed build-essential:
sudo apt-get install build-essential
2) installed libusb (since my try to build the package revealed the absence of usb.h):
sudo apt-get install libusb-dev
And it is OK! The mspdebug (v.023) is compiled and successfully tested!
So, Linux Mint 17.2 (at least) requires installing some libs to a GCC, the most basic is build-essential.
assert.h is not part of gcc, it's a part of glibc.
Most likely, your Linux distribution puts the system headers into a separate package that you need to install.
Fedora, for examples, puts the header files in the glibc-headers package. However, you can't be using Fedora, because Fedora's gcc package has a dependency on glibc-headers, to make sure that it gets pulled in.
Whatever Linux distribution you're using, you need to research which distribution package will install the system header files you need to build stuff with.

using older version of a shared linux library while compiling C

I am trying to use libfann version 2.0.1 instead of the newest version 2.2.0, but could not figure out how to do so. Any thoughts on how to do that?
normally that works perfectly:
gcc fann_calculator.c -o run_fann_calculator -lfann -lm
where fann_calculator.c contains a program that calls a neural network.
Thanks
It depends upon where the two libraries sit. If they are installed in the same directory (e.g. both installed in /usr/lib/) you'll probably get the youngest one.
I suggest to carefully read the ld.so(8) and ldd(1) man pages. You certainly can trace what library is loaded (with e.g. the LD_DEBUG envirnonment variable). Don't forget to re-run ldconfig appropriately after library installation.
You could also play some LD_LIBRARY_PATH trick; for instance, set it to $HOME/lib:/usr/lib and install appropriate symlinks in your $HOME/lib/ to the precise library you want. For instance, you might do
ln -s /usr/lib/libfann.so.2.0.1 $HOME/lib/libfann.so.2
export LD_LIBRARY_PATH=$HOME/lib:/usr/lib:/lib
then check with ldd run_fann_calculator that you get the expected [version of the] libfann library.
Don't forget to read the Program Library Howto. You might want to pass appropriate flags to ld such as -rpath. You may need to pass them using gcc, perhaps with Gcc Link Options such as -Wl

Using GHC, cabal with GMP installed in user-space

I have been trying to install Haskell Platform and cabal-install installed on Linux in user-space on a system that doesn't have the GNU Multi-Precision package (GMP) installed.
I managed to get GHC-6.12.1 installed and GHCi working by setting up LB_LIBRARY_PATH to point at the lib directory where I installed GMP, but then ran into problems in the next step, getting cabal-install to work. It kept trying to (statically) link to GMP.
This fails because the GMP is not installed in the system and ld hasn't a clue where to find the libraries, and there is no environment variable (that I am aware of) that can tell ld where to find the user-installed GMP, and (apparently) no way of telling configuring Cabal to supply the relevant -L flag.
After much fruitless searching and hacking attempts I hit on the absurdly simple idea of installing my own ld shell script that invokes the system ld with the appropriate -L flag.
This is shell scripting 101, of course:
#!/bin/sh
/usr/bin/ld -L$HOME/gnu/lib "$#"
With this script installed in a directory on my PATH ahead of /usr/bin all the problems seem to have gone away.
Basically, your ghc is not working yet. Yes, it can compile things, but it cannot link programs because it needs to link them to gmp.
What we can do is to edit some core package, e.g. the rts package, so that ghc will always use the right -L flag:
ghc-pkg describe rts > rts.pkg
vi rts.pkg # add the gmp dir to the `library-dirs` field
sudo ghc-pkg update rts.pkg

Resources