Install gcc 4.7 but cannot run program sucessfully - c++

I need to use C++ 11, so I updated my GCC from 4.1 to 4.7. I compile the source code and make install it. gcc -version will show 4.7.0 (everything looks good). I compiled my program using:
g++ -O2 -std=c++11 -o wdSer wdSer.cpp
After that I run my program ./wdSer, there are some information as follows:
./wdSer: /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.9' not found (required by ./wdSer)
./wdSer: /usr/lib64/libstdc++.so.6: version `CXXABI_1.3.5' not found (required by ./wdSer)
./wdSer: /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.10' not found (required by ./wdSer)
./wdSer: /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.11' not found (required by ./wdSer)
Who can tell me how to solve it?

First try this:
LD_LIBRARY_PATH=/usr/local/lib64:$LD_LIBRARY_PATH ./wdSer
/usr/local/lib64 is the default library directory for a 64bit build of gcc .
Setting LD_LIBRARY_PATH to contain that directory tells the linker to look in that directory for library files.
If that does not work, look at the output of g++ -v
On my system, I get this:
$ g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/local/gcc-4.8.2/libexec/gcc/x86_64-unknown-linux-gnu/4.8.2/lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with: ../gcc-4.8.2/configure --prefix=/usr/local/gcc-4.8.2 --with-isl=/usr/local/isl-0.12.2 --with-cloog=/usr/local/cloog-0.18.1
Thread model: posix
gcc version 4.8.2 (GCC)
In this output, you are looking for a directory following --prefix. Add /lib64 to the end of that prefix, and you'll have your library directory.
On my system, it's /usr/local/gcc-4.8.2 , so I need the linker to look in /usr/local/gcc-4.8.2/lib64 to find my libstdc++ .
So I run programs like this:
LD_LIBRARY_PATH=/usr/local/gcc-4.8.2/lib64:$LD_LIBRARY_PATH ./a.out
If you don't want to set your LD_LIBRARY_PATH before running your programs, you should build them with -Wl,-rpath= , like this:
$ g++ -std=c++11 -o wdSer -Wl,-rpath=/usr/local/lib64/ wdSer.cc
You can use ldd on a program to see where the shared libraries it is linked to are found:
$ ldd a.out
linux-vdso.so.1 => (0x00007fff8a506000)
libstdc++.so.6 => /usr/local/gcc-4.8.2/lib64/libstdc++.so.6 (0x00007fa3c6aaf000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fa3c6811000)
libgcc_s.so.1 => /usr/local/gcc-4.8.2/lib64/libgcc_s.so.1 (0x00007fa3c67fa000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa3c646f000)
/lib64/ld-linux-x86-64.so.2 (0x00007fa3c6bbc000)
Here, a.out is a program I built with the option -Wl,-rpath=/usr/local/gcc-4.8.2/lib64 , so the linker looks there first, and finds the libstdc++ that goes with my gcc 4.8.2 install.
Please see the documention for the -v flag: http://gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/Overall-Options.html#Overall-Options (and search for -v )
the -Wl flag : http://gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/Link-Options.html#Link-Options (and scroll down to the bottom)
and the -rpath flag: https://sourceware.org/binutils/docs-2.24/ld/Options.html#Options (and search for -rpath)

Related

Setting compiler library search path not working

I built a native compiler for aarch64. The built was successful. I'm having problems though, specifying the glibc (libc.so) library to link against. I followed the suggestion in this link, about compiling with multiple glibc, but is not working.
The environment:
ARM 64bit machine.
A toolchain in toolchain_dir/bin/aarch64-linux-g++.
A sysroot directory in toolchain/sysroot/lib, which contains the lib.so.6 (glibc 2.25) and libstdc++.so (6.0.22) libraries and also the ld-linux-aarch64.so.1 linker.
The /lib64 directory contains the libc.so.6 (glibc 2.17) and libstdc++.so (6.0.19), old versions.
What I tried:
I tried to compile a simple program as:
$aarch-64-linux-g++ file.cpp -o out \
-L/home/user/toolchain/sysroot/lib -lc -lstdc++ \
-Wl,--rpath=/home/user/toolchain/sysroot/lib \
-Wl,--dynamic-link=/home/user/toolchain/sysroot/lib/ld-linux-aarch64.so.1
But I'm getting the error "/lib64/libstdc++.so.6: version GLIBCXX_3.4.20 not found". The error discloses that the rpath is not working, as is still looking into /lib64 library, instead of toolchain/sysroot/lib which contains the GLIBCXX_3.4.20 (libstdc++.so.6).
Next, I moved the toolchain/sysroot/lib/libstdc++.so.6 to /lib64, and compile again with the same command above, now getting the error: "/lib64/libstdc++.so.6 version GLIBC_2.18 not defined". The error shows the new built libstdc++.so.6 trying to find the new built glibc-2.25, but is failing as is searching in the wrong directory path in /lib64.
Next, I set the LD_LIBRARY_PATH=/home/user/toolchain/sysroot/lib. But right after setting this variable I get segmentation faults.
Do you have ideas why this is happening? How could I solve this issue? Thanks!
Edit:
Below more information from compiler, for g++ -v removed part of the output as is really long:
$aarch64-unknown-linux-gnueabi-g++ -v
Target: aarch64-unknown-linux-gnueabi
Configured with: --build=x86_64-build_pc-linux-gnu --host=aarch64-host_unknown-linux-gnueabi --target=aarch64-unknown-linux-gnueabi --enable-gold --disable-nls --disable-multilib --with-local-prefix=/home/common/userX/x-tools/HOST-aarch64-unknown-linux-gnueabi/aarch64-unknown-linux-gnueabi/aarch64-unknown-linux-gnueabi/sysroot --enable-long-long
gcc version 6.3.1 20170109 (crosstool-NG crosstool-ng-1.23.0)
$file aarch64-unknown-linux-gnueabi-g++
ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 4.10.8, stripped

/lib64/libstdc++.so.6: version `GLIBCXX_3.4.20' required by /lib/libmysqlcppconn.so.7

Is it possible that there are 2 versions of libstdc++.so.6 installed, and while compiling it is using a different version
In my code I am reading a binary file and storing the data in mysql server.
While compiling the file. The file compiles properly.
Command used for compiling
g++ -std=c++11 -Wall -I/usr/include -o mkt MtkF.cpp -L/usr/lib -lmysqlcppconn
While running the file I get and error as -
libstdc++.so.6: version `GLIBCXX_3.4.20' required by /lib/libmysqlcppconn.so.7
libstdc++.so.6: version `GLIBCXX_3.4.21' required by /lib/libmysqlcppconn.so.7
OS CentOS
On running this command -
strings /usr/lib64/libstdc++.so.6 | grep LIBCXX
It return values till GLIBC19
Have looked at other solutions also, but no luck.

Which version of glibc should be used when release my *.so file?

I'm working on a shared library which support SSL connection and transmission. I want to release it as a *.so file. After compiling it in my Ubuntu14.04(64bit Desktop) with g++ 4.8.2, it can not work in the CentOS5.8.
The First Round
I compile the shared library with following command:
g++ -v -shared -Wl,-soname,libmyssl.so.1,-o libmyssl.so.1.0 myssl.o -lz -lssl -lcrypto
I use command objdump -p libmyssl.so.1.0|grep NEEDED to know it depends on following libraries:
NEEDED libz.so.1
NEEDED libssl.so.1.0.0
NEEDED libcrypto.so.1.0.0
NEEDED libstdc++.so.6
NEEDED libc.so.6
Then I write a demo to use libmyssl.so.1.0.
g++ -D UNIX64 -o ssldemo ssldemo.cpp ./libmyssl.so.1.0 -lz -lssl -lcrypto
I compile the demo in Ubuntu14.04(the same version), it works fine.
I compile the demo in CentOS(openssl 0.9.8e), it linked failed because invalid openssl's version
The Second Round
I removed the "-lz lssl -lcrypto", so the command as following
g++ -v -shared -Wl,-soname,libmyssl.so.1,-o libmyssl.so.1.0 myssl.o
I use command objdump -p libmyssl.so.1.0|grep NEEDED to know it depends on following libraries:
NEEDED libstdc++.so.6
NEEDED libc.so.6
I use the libmyssl.so.1.0 in above demo code in the same way:
g++ -D UNIX64 -o ssldemo ssldemo.cpp ./libmyssl.so.1.0 -lz -lssl -lcrypto
I compile the demo in Ubuntu14.04(the same version), it works fine.
I compile the demo in CentOS(openssl 0.9.8e), it didn't report ssl linked errors, but it report glibc linked errors as follows:
undefined reference to `memcpy#GLIBC_2.14'
After updating CertOS's glibc, the demo work fine.
The Third Round
I try to remove the depends to "libc.so.6" and "libstdc++.so.6", so I added option "-nodefaultlibs" to the compile command:
g++ -nodefaultlibs -v -shared -Wl,-soname,libmyssl.so.1,-o libmyssl.so.1.0 myssl.o
I use command objdump -p libmyssl.so.1.0|grep NEEDED only get empty string.
I use command ldd libmyssl.so.1.0 get result "statically linked", no sure why it said "statically linked".
I use the libmyssl.so.1.0 in above demo code in the same way:
g++ -D UNIX64 -o ssldemo ssldemo.cpp ./libmyssl.so.1.0 -lz -lssl -lcrypto
It always report following error both in Ubuntu14.04 and CentOS5.8:
Ubuntu:
hidden symbol `atexit' in /usr/lib/x86_64-linux-gun/libc_nonshared.a(atexit.oS) is referenced by DSO
/usr/bin/ln: final link failed: Bad value
CentOS:
hidden symbol `atexit' in /usr/lib64/libc_nonshared.a(atexit.oS) is referenced by DSO
/usr/bin/ln: final link failed: Nonrepresentable section on output
Questions:
Which version of GLIBC should be linked when I compile my *.so file so that it can work fine in as many as possible Linux?
Do have a way to avoid the dependency to the GLIBC? I tried it in The Third Round but failed.
Any other suggestions ?
Which version of GLIBC should be linked when I compile my *.so file
so that it can work fine in as many as possible Linux?
You should select the oldest distro that you want to target and build on this one. This would ensure that your library would require the minimum possible Glibc version. So simply select the distro with oldest Glibc and build there.
Version of your Glibc is usually encoded in libc.so name (e.g. /lib64/libc-2.12.so) but you can also do
$ strings //lib64/libc-2.12.so | grep GLIBC
GLIBC_2.2.5
GLIBC_2.2.6
...
GLIBC_2.12
GLIBC_PRIVATE
Do have a way to avoid the dependency to the GLIBC? I tried it in The Third Round but failed.
Writing entirely Glibc-independent library sounds like an overkill (you'll need to re-implement IO, memcpy, etc., with lower quality/performance compared to Glibc). Are you sure you want to go down this path?
Any other suggestions ?
For complete applications two common solutions are
static linking
bundling them together with stdlibs they were linked against (they'll of course need to be run with special LD_LIBRARY_PATH or -Wl,-rpath)
But in your case (isolated shared library) targeting the lowest supported Glibc seems to be the only option.

When I include a shared library, my executable is looking for two versions of it

When I make my program with -larmadillo, I get an executable which wants two versions of it:
$ ldd ./a.out | grep armadillo
$ libarmadillo.so.7 => /usr/lib/x86_64-linux-gnu/libarmadillo.so.7 (0x00007fd5e29a0000)
$ libarmadillo.so.4 => not found
Can anyone point me in the right direction? This isn't making any sense to me!
Background: I initially installed libarmadillo via sudo apt-get install libarmadillo-dev, then I realised I needed to build it with a specific parameter (64 bit words enabled), so I uninstalled it via sudo apt-get remove libarmadillo-dev then downloaded the latest version, configured and make/make installed it. Presumably I only have one version of libarmadillo on my system - I do not see any old libraries in the usual places.
Thanks
EDIT:
My Makefile is:
CC= g++
CFLAGS= -Lcontrib/armadillo-7.400.1 -L/usr/include -Lcontrib/mlpack-2.0.1/build/lib -fpermissive -std=c++11 -O0 -g -Wall
LDFLAGS= -lmlpack -larmadillo
The verbose output of ldd is interesting, I think?
$ ldd -v ./a.out | grep armadillo
$ libarmadillo.so.7 => /usr/lib/x86_64-linux-gnu/libarmadillo.so.7 (0x00007fd5e29a0000)
$ libarmadillo.so.4 => not found
$ /usr/lib/x86_64-linux-gnu/libarmadillo.so.7:
The latter section (which lists dependences for libarmadillo.so.7) is:
/usr/lib/x86_64-linux-gnu/libarmadillo.so.7:
ld-linux-x86-64.so.2 (GLIBC_2.3) => /lib64/ld-linux-x86-64.so.2
libc.so.6 (GLIBC_2.2.5) => /lib/x86_64-linux-gnu/libc.so.6
There is no mention of the 'missing' libarmadillo.so.4 in the verbose output, which I find quite strange.
I think I've figured it out, but the results aren't particularly comforting.
I reinstalled mlpack which has a dependency into libarmadillo, and then rebuilt, and the requirement for libarmadillo.so.4 is gone.
The process that I think happened is I:
Installed old version of libarmadillo
Installed libmlpack configured with old version
Realised I needed a newer version of libarmadillo, so uninstalled old libarmadillo and installed a new one.
Rebuilt mlpack using cmake / make but did not make install
Made my executable
Now have an executable which is is pointing to mlpack which requires the old libarmadillo, but it also points to the new libarmadillo
Once I make install the rebuilt mlpack, my problems go away. I am surprised that the verbose output of ldd didn't flag any reason as to why it was looking for libarmadillo.so.4 (namely that there was a dependency from libmlpack on the old library) - should ldd be able to do this?
Sometimes linux creates many symbolic link of one dynamic library. I don't know why but no matter as there is no inconvenient for that. So, you can just create a new symbolic link like this : ln -s path_to_my_so_lib/my_lib.so /usr/lib/x86_64-linux-gnu/libarmadillo.so.4

How can one build openssl on ubuntu with a specific version of zlib?

Background
I'd like to build OpenSSL against a specific version of zlib so that all of my code is built by me. I do this for many of the libraries I use so that I don't get different behaviour on different versions of the operating system. I understand that this isn't strictly necessary, but I wanna.
What I've Done
I've built zlib in ~/zlib/zlib-1.2.7, and installed zlib to ~/zlib/lib and ~/zlib/include.
(Note that I've simplified all paths in this post by substituting my working directory for '~')
I've built openssl passing these arguments to ./config
--with-zlib-lib=~/zlib/lib
--with-zlib-include=~/zlib/include
When I build openssl, I can see that the appropriate -I argument is being passed to GCC
./config --prefix=~/openssl --openssldir=openssl/ssl threads zlib-dynamic shared --with-zlib-lib=~/zlib/lib --with-zlib-include=~/zlib/include && make && make install
. . .
...many lines of output...
. . .
gcc -I.. -I../.. -I../modes -I../asn1 -I../evp -I../../include -I/home/ubuntu/zlib/include -fPIC -DOPENSSL_PIC -DZLIB_SHARED -DZLIB -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -Wa,--noexecstack -m64 -DL_ENDIAN -DTERMIO -O3 -Wall -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DMD5_ASM -DAES_ASM -DVPAES_ASM -DBSAES_ASM -DWHIRLPOOL_ASM -DGHASH_ASM -c -o cm_pmeth.o cm_pmeth.c
OpenSSL builds successfully.
The Problem
I check what version of zlib is being linked with the command ldd libssl.so.
ubuntu#lemming012:~/ben/code/optimiser/libs/3rdParty/openssl/lib$ ldd libssl.so
linux-vdso.so.1 => (0x00007fff3e7ff000)
libcrypto.so.1.0.0 => /lib/x86_64-linux-gnu/libcrypto.so.1.0.0 (0x00007f
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f289bcab000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f289baa6000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f289b88f000)
/lib64/ld-linux-x86-64.so.2 (0x00007f289c6c7000)
I expect to see ldd reporting my own libz file in the list.
Instead, ldd reports that libssl is linked to my system installed version of libz. The results are identical if I copy my own version libz.so.1 into the libssl 'lib' directory before running ldd in that same directory.
Question
What have I done wrong? How can I get OpenSSL to link to my version of zlib instead of the version installed on the system?
Environment
uBuntu 13.04 x64
compiling with GCC
building with Make
The answer turns out to be, you need to set an rpath with a syntax similar to the following. I do mine in a Makefile, which is the reason for the double '$'.
LDFLAGS += -Wl,-rpath,'$$ORIGIN/../lib'
Now, I don't necessarily need to do this on the library (openssl) itself. I can do this on the calling executable instead. If the library has no rpath, the rpath on the executable gets used next. In short, I don't need to stress that ldd -r <library> is returning the wrong path, provided that ldd -r <executable> returns the correct path.
I can test by library with the following command:
env LD_LIBRARY_PATH=$PWD ldd -r <library>
And once my executable is compiled, I can verify everything like this:
ldd -r <executable>
Long story short, everything is working just fine, don't get hung up on what ldd -r <library> is returning, just worry about ldd -r <executable>.
./config --prefix=/data/services/openssl-1.0.2g shared zlib -I/data/services/zlib-1.2.7/include -L/data/services/zlib-1.2.7/lib