Cannot find -lc and -lm in g++ linux - gcc

I am using Ubuntu and gcc and g++ were working fine but today it showed:
cannot find -lm
cannot find -lc
I searched and found it has something to do with /usr/bin/ld. Which is a symlink (I hope) to lbd.bdf. I pasted that file in the directory from Ubuntu of some friends PC. It didn't work.
I found that -lc means include static library libc.a.
similarly for -lm
I found them in my i386-linux-folders (name was something different).
I tried code blocks but same errors.

The compiler cannot find static glibc, you might have installed only the shared libraries, try:
yum install glibc-static

make sure that your libpath (in g++) points to the directory(ies) that libm.a and libc.a are located in (use the -L option)

ld is the GNU linker.
man ld
ld combines a number of object and archive files, relocates their data and ties up symbol references. Usually the last step in compiling a program is to run ld.
It is uses to link your program with the C library and the C math library. You need to make sure that libc6-dev is installed:
foo#bar: $ dpkg -s libc6-dev
Or more generic, ensure build-essential, which depends on a handful of essential C packages.
foo#bar: $ dpkg -s build-essential

Related

Priority of LIBRARY_PATH with custom gcc installations

Is there a way to get compilers to prefer libraries from LIBRARY_PATH instead of system paths. I am particularly looking for Clang. I partially solved the problem for GCC while writing this question, but it's also not quite clear.
Background
LIBRARY_PATH is a convenient environment variable to allow transparently linking libraries in non-standard directories, e.g. user installations, and in my case environment modules that provide different versions of a library.
The idea is to do a module load libfoo/version and the compiler will transparently use the right libfoo.so.
For a shared library, one also needs to set LD_LIBRARY_PATH for ld.so to find the right library. If there are multiple libfoo.so in both LD_LIBRARY_PATH and /usr/lib, ld.so specifies that LD_LIBRARY_PATH is searched before default paths.
Problem
I have encountered issues when the library defines a soname - which is different between the two libfoo.so versions (which are symlinks to libfoo.so.1 and libfoo.so.2 respectively) in /usr/lib and LIBRARY_PATH. Then ld will link against the soname in /usr/lib and LD_LIBRARY_PATH can no longer prioritize the intended library.
I first encountered this with boost, but here's a small example:
echo "void foo() {}" > foo.c
# create an old libfoo version in /usr/lib
sudo gcc foo.c -fpic -shared -o /usr/lib/libfoo.so.1 -Wl,-soname,libfoo.so.1
sudo ln -s libfoo.so.1 /usr/lib/libfoo.so
# create the new libfoo that we want to transparently override
mkdir -p /tmp/XXX/lib
gcc foo.c -fpic -shared -o /tmp/XXX/lib/libfoo.so.2 -Wl,-soname,libfoo.so.2
ln -s libfoo.so.2 /tmp/XXX/lib/libfoo.so
export LIBRARY_PATH=/tmp/XXX/lib
export LD_LIBRARY_PATH=/tmp/XXX/lib
echo "void foo(); int main() { foo(); }" > main.c
gcc main.c -lfoo
ldd a.out| grep foo
# under some conditions this shows libfoo.so.1 instead of .2
libfoo.so.1 => /usr/lib/libfoo.so.1
GCC
I initially encountered this issue with a custom installation of GCC while it was working as expected for the system installation.
gcc --print-search-dirs reveals a pattern:
/tmp/XXX/lib/x86_64-pc-linux-gnu/7.2.0/
/tmp/XXX/lib/x86_64-linux-gnu/
/tmp/XXX/lib/../lib64/
/opt/gcc/7.2.0/lib/gcc/x86_64-pc-linux-gnu/7.2.0/
/opt/gcc/7.2.0/lib/gcc/x86_64-pc-linux-gnu/7.2.0/../../../../x86_64-pc-linux-gnu/lib/x86_64-pc-linux-gnu/7.2.0/
/opt/gcc/7.2.0/lib/gcc/x86_64-pc-linux-gnu/7.2.0/../../../../x86_64-pc-linux-gnu/lib/x86_64-linux-gnu/
/opt/gcc/7.2.0/lib/gcc/x86_64-pc-linux-gnu/7.2.0/../../../../x86_64-pc-linux-gnu/lib/../lib64/
/opt/gcc/7.2.0/lib/gcc/x86_64-pc-linux-gnu/7.2.0/../../../x86_64-pc-linux-gnu/7.2.0/
/opt/gcc/7.2.0/lib/gcc/x86_64-pc-linux-gnu/7.2.0/../../../x86_64-linux-gnu/
/opt/gcc/7.2.0/lib/gcc/x86_64-pc-linux-gnu/7.2.0/../../../../lib64/
/lib/x86_64-pc-linux-gnu/7.2.0/
/lib/x86_64-linux-gnu/
/lib/../lib64/
/usr/lib/x86_64-pc-linux-gnu/7.2.0/
/usr/lib/x86_64-linux-gnu/
/usr/lib/../lib64/
/tmp/XXX/lib/
/opt/gcc/7.2.0/lib/gcc/x86_64-pc-linux-gnu/7.2.0/../../../../x86_64-pc-linux-gnu/lib/
/opt/gcc/7.2.0/lib/gcc/x86_64-pc-linux-gnu/7.2.0/../../../
/lib/
/usr/lib/
In addition to the normal search priority - where LIBRARY_PATH comes before system paths, GCC prioritizes a few "prefixes", including ../lib64. This can be worked around by creating another symlink:
ln -s lib /tmp/XXX/lib64
I thought this was related to the --libdir parameter during configure, which I omitted and is /usr/lib in the system installation, but even if i specify --libdir=$PREFIX/lib --libexecdir=$PREFIX/lib, it prefers ../lib64.
How to compile or control gcc at runtime so that it at least uses the ../lib instead of ../lib64 postfix?
Clang
Clang is even more uncooperative. It does not include LIBRARY_PATH in the output for --print-search-dirs and does not even include a -L/tmp/XXX/lib to it's call to ld if the libfoo.so can be found already in /usr/lib.
How can I get Clang to prioritize my library path transparently?
Notes
Examples are from Archlinux, but I also tested under Ubuntu 16.04 which behaves similarly.
Related questions for GCC: Why does g++ look in LIBRARY_PATH/../lib64 and where is this documented? and g++ searches /lib/../lib/, then /lib/.
Overriding the search order with -L works, but is not transparent.
gcc --print-search-dirs lists more directories than gcc -v. The latter filters out non-exiting paths.
I found out the reason why a custom installation of GCC is different. Debian distribution patches the GCC makefiles, that's how it gets the right priority of LIBRARY_PATH. Before building GCC, find gcc/config/i386/t-linux64 and there change all MULTILIB_OSDIRNAMES to these lines:
MULTILIB_OSDIRNAMES = m64=../lib$(call if_multiarch,:x86_64-linux-gnu)
MULTILIB_OSDIRNAMES+= m32=../lib32$(call if_multiarch,:i386-linux-gnu)
MULTILIB_OSDIRNAMES+= mx32=../libx32$(call if_multiarch,:x86_64-linux-gnux32)
Also add --libexecdir=/your/custom/path/lib --libdir=/your/custom/path/lib to configure.

Fedora 21 with clang, without gcc

Can you (reasonably) get Fedora 21 to where it only has llvm/clang/libc++/libc++abi? (I found some things suggesting no, but they were all about 3 years old, and llvm/clang has come a long way since then.)
With a fresh install, I tried
yum install gcc gcc-c++
(downloaded, built, installed llvm/cfe(clang)/compiler-rt/libcxx/libcxxabi from svn)
yum remove gcc gcc-c++
added to /etc/profile: export CC=/usr/local/bin/clang \ export CXX=/usr/local/bin/clang++
(in case of hard wiring)
ln -s /usr/local/bin/clang /usr/local/bin/gcc
ln -s /usr/local/bin/clang /usr/local/bin/cc
ln -s /usr/local/bin/clang++ /usr/local/bin/g++
ln -s /usr/local/bin/clang++ /usr/local/bin/c++
ldconfig
I was all happy, then went to build something, and I got:
ld: cannot find crtbegin.o
ld: cannot find -lgcc
ld: cannot find -lgcc_s
clang -v includes
Found candidate GCC installation: /usr/lib/gcc/x86_64-redhat-linux/4.9.2
ldconfig && ldconfig -p | grep libgcc does show
libgcc_s.so.1 (libc6,x86-64) => /lib64/libgcc_s.so.1
And /lib64 is a symlink to /usr/lib64. And, /usr/lib64/libgcc_s.so.1 is a symlink to /usr/lib64/libgcc_s-4.9.2-20150212.so.1, which exists as a real file (92816 bytes.)
So, I don't get what ld's problem is on -lgcc_s. crtbegin is nowhere to be found, and gcc (no _s) is nowhere to be found.
yum install libgcc says it's already installed and latest version, nothing to do.
Since I have an installed clang source build, can I re-build clang, this time using clang rather than gcc, to get rid of the dependency? (Maybe then the "candidate GCC installation" bit goes away.)
Can I force -stdlib=c++ and -lc++abi to be default, or at least have libc++ and libc++abi installed without gcc?
Having spent some time trying to get clang to work with libc++ and libc++abi without GCC, I have found that it is indeed possible, even if a bit problematic given the current state of LLVM/clang. In addition to small test programs, I've been able to build CMake and some other software packages written in C++ with no GCC installed, and with the resulting binaries being independent of libstdc++; they only depend on libc++/libc++abi according to ldd output. Unfortunately, I haven't been able to build clang itself with clang that was build using GCC. I've been experimenting on different Linux platforms (Fedora 21 32-bit, Amazon Linux release 2015.3 (RPM-based) 64-bit, CentOS 7.1 64-bit, and Ubuntu 14.04 64-bit).
Even though one can build software with clang using libc++/libc++abi without dependency on libstdc++ and without GCC compiler present, a typical Linux installation is so tied to libgcc and libstdc++ that getting rid of these is not practical. Try removing these two packages and you will see how much of the system depends on them. Even on FreeBSD 10.1, with clang being the default compiler and no GCC installed, libgcc.a, libgcc_s.so, and a few crt*.o files are used when building a program as revealed by the -v option. Also, on FreeBSD 10.1, resulting binaries depend on libgcc according to ldd. On Ubuntu, which has dpkg as the package manager, the files
libgcc.a
libgcc_s.so
crtbegin.o
crtbeginT.o
crtbeginS.o
crtendS.o
crtend.o
are in the libgcc-devel package, while on an RPM-based system, such as Fedora, these are in the gcc package. In addition, you might possibly need these files, even though I didn't need them for the code I tried building:
crtfastmath.o
crtprec32.o
crtprec80.o
crtprec64.o
Thus one might argue that the aforementioned files better belong in libgcc, rather than in gcc. As far as I can tell, the following needs to be done on an RPM-based system before removing the gcc package:
1) Create the symlink
libgcc_s.so -> libgcc_s.so.1
in whatever directory libgcc_s.so.1 is located.
2) Copy the crt*.o files listed above to that directory.
3) In the same directory create the symlink (libstdc++.so.x should already be there; x is a number):
libstdc++.so -> libstdc++.so.x
You only need this if you are going to use libstdc++; this isn't needed if you only plan to use libc++. On some
systems libstdc++.so, which is a symlink to libstdc++.so.x belonging to the libstdc++ package, is placed by the libstdc++-devel package into the GCC library directory, so you can remove that directory after uninstalling GCC and just create the symlink in the same directory where libstdc++.so.x lives.
Now you should be able to do the following:
1) Build a C program:
clang progname.c
2) Build a C++ program using libstdc++ headers/libs:
clang++ -I<location of headers> progname.cpp
On RPM-based systems I've looked at, the libstdc++ headers are part of the libstdc++-devel package and their location can be found from rpm -ql on the package.
3) Build a C++ program using libc++ headers/libs:
clang++ -I/<location of headers> progname.cpp -nodefaultlibs -lc++ -lc++abi -lm -lc -lgcc -lgcc_s
The location of the headers is wherever they were installed when you built LLVM+clang etc.
Please see http://libcxx.llvm.org/ for additional information. When building C++ code using libc++/libc++abi, you may use -stdlib=libc++ instead of the -I flag, but in my testing that only worked with clang built from source, not with clang installed from a repository (you can install clang from repo and use it to build libc++/libc++abi; or you can use gcc to build libc++(abi), then remove gcc and use the libs with the repo-provided clang).
When configuring a software package to build it using clang + libc++, you might need to set the following:
LIBS="-nodefaultlibs -lc++ -lc++abi -lm -lc -lgcc_s -lgcc"
CXX=clang++
CXXFLAGS="-stdlib=libc++"
CC=clang
Please note that to configure CMake source in order to build it I had to use a wrapper script like this:
#!/bin/bash
MYLFLAGS="-nodefaultlibs -lc++ -lc++abi -lm -lc -lgcc_s -lgcc"
# Catch the case when we only want to compile; this helps us avoid some warnings:
if echo "$#" | egrep "(^-c | -c | -c$)" >/dev/null 2>&1; then
MYLFLAGS=""
fi
/usr/local/bin/clang++ -stdlib=libc++ "$#" $MYLFLAGS
It might be useful for other purposes as well.
For more information please see my article at http://www.omniprog.info/clang_no_gcc.html

Compiling gcc-4.1

Unfortunately I'm forced to use gcc-4.1 and I'm using debian wheezy. Since gcc-4.1 is not in repository I'm trying to build gcc from sources.
But I'm getting compiling error:
/usr/bin/ld: skipping incompatible /usr/lib/x86_64-linux-gnu/libc.so when searching for -lc
/usr/bin/ld: skipping incompatible /usr/lib/x86_64-linux-gnu/libc.a when searching for -lc
/usr/bin/ld: i386:x86-64 architecture of input file `/usr/lib/x86_64-linux-gnu/crti.o' is incompatible with i386 output
/usr/bin/ld: i386:x86-64 architecture of input file `/usr/lib/x86_64-linux-gnu/crtn.o' is incompatible with i386 output
It looks that ld is picking wrong version of libraries, but I checked my /usr/lib32 and /usr/lib/x86_64-linux-gnu/ and it contains those files:
/usr/lib32/libc.a
/usr/lib32/libc.so
/usr/lib32/crtn.o
/usr/lib32/crti.o
/usr/lib/x86_64-linux-gnu/libc.a
/usr/lib/x86_64-linux-gnu/libc.so
/usr/lib/x86_64-linux-gnu/crtn.o
/usr/lib/x86_64-linux-gnu/crti.o
And ld should have access to them
~$ echo $LIBRARY_PATH
/usr/lib/x86_64-linux-gnu:/usr/lib32/
So I have no idea where the problem is.
I managed to work around the problem.
Run configure with:
./configure --disable-multilib ...
But than I encountered another problem with makeinfo, if you have newer version >=4.10 than it might not be found by configure. So simple fix in generated makefile worked for me:
Change this line:
MAKEINFO = /home/lecopivo/Downloads/gcc412/gcc412/gcc-4.1.2/missing makeinfo
To this:
MAKEINFO = makeinfo
I found this helpful.
LD_LIBRARY_PATH is only for running programs already linked.
You probably need to set LDFLAGS when you configure gcc:
./configure LDFLAGS="-L/usr/lib32" .....
It might be LDFLAGS_FOR_HOST or LIBS or something like that though.
I had this problem recently and finally solved it this way:
ln -s /usr/lib32 /usr/lib/i386-linux-gnu
Notes:
I assumed you do not have /usr/lib/i386-linux-gnu directory in your 64bit linux. If this directory exists and is empty, please delete it and make the above link.
If the directory already exists and is not empty, you have to make links inside it for (32bit) libraries which cause build error one by one; e.g.:
ln -s /usr/lib32/crti.o /usr/lib/i386-linux-gnu/crti.o
ln -s /usr/lib32/crtn.o /usr/lib/i386-linux-gnu/crtn.o
...
If 32bit development libraries are not installed, you may have to install them first. I've searched different forums and found that installing following set of packages in ubuntu will provide them:
libc6-dev libc6-dev-i386
gcc-multilib g++-multilib
zlib1g-dev lib32z1-dev
libncurses5-dev lib32ncurses5-dev libncursesw5-dev lib32ncursesw5-dev
Also adjust LD_LIBRARY_PATH and LIBRARY_PATH variables so that they contain /usr/lib/i386-linux-gnu and /usr/lib/x86_64-linux-gnu (i.e. multiarch lib-dirs). I am not sure which one of above variables is effective, so I adjust both of them the same.
If you use ./configure --disable-multilib as it is frequently suggested on web, though gcc will be built, but when you want to use that gcc for compiling e.g. legacy grub, you probably get error of "gcc cannot build executable" (or such).
Optionally, you can make similar linking for these pair of libdirs:
ln -s /lib32 /lib/i386-linux-gnu
Doing so, I managed to compile gcc-3.4.6 in a Ubuntu 16.04.6-amd64 used for compiling old 32bit programs like SDL 1.2 and legacy GRUB4DOS 0.4.4.
Also take a look at my answer to similar (though opposite) error here.
Good luck.

How to link to a specific version of the standard library (with gcc)

I've installed GCC 3.4 to /opt/gcc-3.4, and I'm using it to compile legacy code which is incompatible with GCC 4. This also means old versions of the C(++) standard libraries, binutils, and utility libraries.
It works fine for some libraries, but fails when compiling libtiff, because it picks up the system libraries in /usr/lib (see output below). This might be an autotools/configure issue, but I'm not sure. I can't find a configure switch or environment variable, and I'd rather not modify my system /usr/lib/libc.so .
So how to make sure it links to the standard library in /opt/gcc-3.4.4/lib, and ignores /lib and /usr/lib completely?
Output of make (excerpt):
libtool: link: g++ -shared -nostdlib /usr/lib/crti.o /opt/gcc-3.4.3/lib/gcc/i686-pc-linux-gnu/3.4.3/crtbeginS.o .libs/tif_stream.o -Wl,--whole-archive ../port/.libs/libport.a -Wl,--no-whole-archive -Wl,-rpath -Wl,/home/jason/d0src34/prereq/tiff-3.9.4/libtiff/.libs -Wl,-rpath -Wl,/opt/gcc-3.4.3/lib -Wl,-rpath -Wl,/home/jason/d0src34/prereq/usr/lib -Wl,-rpath -Wl,/opt/gcc-3.4.3/lib ../libtiff/.libs/libtiff.so -L/usr/lib /usr/lib/libjpeg.so -lz -L/opt/gcc-3.4.3/lib/gcc/i686-pc-linux-gnu/3.4.3 -L/opt/gcc-3.4.3/lib/gcc/i686-pc-linux-gnu/3.4.3/../../.. /opt/gcc-3.4.3/lib/libstdc++.so -L/home/jason/Downloads/gcc-3.4.3/build/i686-pc-linux-gnu/libstdc++-v3/src -L/home/jason/Downloads/gcc-3.4.3/build/i686-pc-linux-gnu/libstdc++-v3/src/.libs -L/home/jason/Downloads/gcc-3.4.3/build/gcc -lm -lc -lgcc_s /opt/gcc-3.4.3/lib/gcc/i686-pc-linux-gnu/3.4.3/crtendS.o /usr/lib/crtn.o -Wl,-soname -Wl,libtiffxx.so.3 -o .libs/libtiffxx.so.3.9.4
/home/jason/d0src34/prereq/usr/bin/ld:/usr/lib/libc.so: file format not recognized; treating as linker script
/home/jason/d0src34/prereq/usr/bin/ld:/usr/lib/libc.so:5: parse error
I've found a (hackish) answer to my own question:
I've been using binutils 2.15, because later versions have an incompatibility with GCC 3.4. In more recent versions, the format of /usr/lib/libc.so has changed, and the old binutils can't parse it.
I temporarily commented out the last line (with "GROUP"), and my code compiled:
/* GNU ld script
Use the shared library, but some functions are only in
the static library, so try that secondarily. */
OUTPUT_FORMAT(elf32-i386)
/* GROUP ( /lib/libc.so.6 /usr/lib/libc_nonshared.a AS_NEEDED ( /lib/ld-linux.so.2 ) ) */
However, I'm not really satisfied, since I can hardly tell other people who want to use the code to edit their system files. Also, I'm not sure if I've linked it to the correct glibc version, since the system /usr/lib is still in the search path, so I can't tell for sure if the binaries will work on other systems.

GLIBCXX_3.4.9 not found

I have a problem concerning libstdc++.so.
I installed a new version of gcc and tried to compile C++ code. The compiling worked, but when I try to execute the binary (m5.opt is its name) I've got the following error:
build/ALPHA_SE/m5.opt: /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.9' not found (required by build/ALPHA_SE/m5.opt).
Do I need to replace libstdc++.so? And if so, where can I download the version I want? On the GCC-website they say libstdc++ is a part of gcc now.
Details
GCC:
I had gcc 4.1.2 before, but I downloaded gcc 4.2.4. From the untarred gcc-directory I executed ./configure; make; sudo make install`.
When I tried to use gcc or g++ to compile, it's default version was still 4.1.2. To overcome this I replaced some links:
mv /usr/bin/gcc /usr/bin/gcc_bak
ln -s /usr/local/bin/gcc gcc
mv /usr/bin/g++ /usr/bin/g++_bak
ln -s /usr/local/bin/g++ g++
GLIBC(++) -- libstdc++:
/usr/lib64/libstdc++.so.6 -> libstdc++.so.6.0.8
/usr/local/lib/libstdc++.so -> libstdc++.so.6.0.9
/lib/libc.so.6 -> libc-2.5.so -> libc-2.5.so
Linux-version:
uname -a gives:
Linux madmax 2.6.18-128.4.1.el5 #1 SMP Tue Aug 4 12:51:10 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux
The problem is that you built your new GCC incorrectly: on Linux you should use
./configure --prefix=/usr
The default installation prefix is /usr/local, which is why make install put gcc and g++ binaries into /usr/local/bin, etc.
What's happening to you now is that you compile and link using the new (symlinked) GCC 4.2.4, but at runtime your program binds to the old /usr/lib64/libstdc++.so.6 (version 6.0.8, instead of required 6.0.9). You can confirm that by running ldd build/ALPHA_SE/m5.opt: you should see that it uses /usr/lib64/libstdc++.so.6.
There are several fixes you could do.
env LD_LIBRARY_PATH=/usr/local/lib64 ldd build/ALPHA_SE/m5.opt
should show you that setting LD_LIBRARY_PATH is sufficient to redirect the binary to correct library, and
LD_LIBRARY_PATH=/usr/local/lib64 build/ALPHA_SE/m5.opt
should just run. You could "bake" this path into m5.opt binary by relinking it with -Wl,-rpath=/usr/local/lib64.
A more permanent solution is to fix the libraries the same way you fixed the binaries:
cd /usr/lib64 && mv libstdc++.so.6 libstdc++.so.6_bak &&
ln -s /usr/local/lib64/libstdc++.so.6 .
An even better solution is to reconfigure the new GCC with --prefix=/usr, and then make all install.
I know this is a very old question, but ...
It's not usually a good idea to replace the system compiler (i.e. the one in /usr) because the entire system will have been built with it and depend on it.
It's usually better to install the new compiler to a separate location and then see the libstdc++ FAQ How do I insure that the dynamically linked library will be found? and Finding Dynamic or Shared Libraries in the manual for how to ensure the correct libstdc++.so is found at runtime.
The other answers here should be fine, but the 'quick and easy' solution if you do happen to have gcc installed to /usr/local/ is to just add the new libs to the LD_LIBRARY_PATH
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib64
You can also check the to see if you have the right versions of GLIBC installed using
strings /usr/lib/libstdc++.so.6 | grep GLIBC
strings /usr/local/lib64/libstdc++.so.18 | grep GLIBC
I got this last tip from another forum so credits due where credits due!

Resources