Setting compiler library search path not working - c++

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

Related

Building GDAL with all libraries static

I want to develop a small program that checks which polygons from a shapefile intersect a given rectangle. This program is to be used in a website (with PHP's exec() command). The problem is, my webserver cannot install GDAL, for reasons unknown to me. So I can't link to the shared libraries. Instead, I must link to static libraries, but these aren't given.
I've downloaded the GDAL source code from here (2.3.2 Latest Stable Release - September 2018), and followed the build instructions from here. Since I already have GDAL working on my Debian, and don't want to mess with it, I followed the "Install in non-root directory" instructions, with some adjusts from the last item in the "Some caveats" section:
cd /home/rodrigo/Downloads/gdal232/gdal-2.3.2
mkdir build
./configure --prefix=/home/rodrigo/Downloads/gdal232/gdal-2.3.2/build/ --without-ld-shared --disable-shared --enable-static
make
make install
export PATH=/home/rodrigo/Downloads/gdal232/gdal-2.3.2/build/bin:$PATH
export LD_LIBRARY_PATH=/home/rodrigo/Downloads/gdal232/gdal-2.3.2/build/lib:$LD_LIBRARY_PATH
export GDAL_DATA=/home/rodrigo/Downloads/gdal232/gdal-2.3.2/build/share/gdal
/usr/bin/gdalinfo --version
build/bin/gdalinfo --version
The first /usr/bin/gdalinfo --version gives 2.1.2 (the previous installed version). The second, build/bin/gdalinfo --version, gives 2.3.2 (the version just built).
By now, my program only uses the ogrsf_frmts.h header, which is in /usr/include/gdal/ or /home/rodrigo/Downloads/gdal232/gdal-2.3.2/build/include/ directory, depending on the build. There's no ogrsf_frmts.a file, but only a libgdal.a. Is this the file I should be linking against? If so, how? I've tried so far:
gcc geofragc.cpp -l:libgdal.a
gcc geofragc.cpp -Wl,-Bstatic -l:libgdal.a
gcc geofragc.cpp -Wl,-Bstatic -l:/home/rodrigo/Downloads/gdal232/gdal-2.3.2/build/lib/libgdal.a
gcc geofragc.cpp -Wl,-Bstatic -l/home/rodrigo/Downloads/gdal232/gdal-2.3.2/build/lib/libgdal.a
gcc geofragc.cpp /home/rodrigo/Downloads/gdal232/gdal-2.3.2/build/lib/libgdal.a
gcc geofragc.cpp -l/home/rodrigo/Downloads/gdal232/gdal-2.3.2/build/lib/libgdal.a
gcc geofragc.cpp -l:/home/rodrigo/Downloads/gdal232/gdal-2.3.2/build/lib/libgdal.a
but nothing works. What am I missing?
EDIT
The second trial (gcc geofragc.cpp -Wl,-Bstatic -l:libgdal.a) is giving the following error:
/usr/bin/ld: cannot find -lgcc_s
/usr/lib/gcc/x86_64-linux-gnu/6/../../../../lib/libgdal.a(gdalclientserver.o): In function `GDALServerSpawnAsync()':
(.text+0x1f5e): warning: Using 'getaddrinfo' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
/usr/bin/ld: cannot find -lgcc_s
collect2: error: ld returned 1 exit status
You can use the gdal-config program to get correct options for compilation and linking. This program is a part of the GDAL library and it has its own options:
hekto#ubuntu:~$ gdal-config --help
Usage: gdal-config [OPTIONS]
Options:
[--prefix[=DIR]]
[--libs]
[--dep-libs]
[--cflags]
[--datadir]
[--version]
[--ogr-enabled]
[--gnm-enabled]
[--formats]
You have to make sure this program is on your search path, or you can create an alias - for example:
alias gdal-config='/home/rodrigo/Downloads/gdal232/gdal-2.3.2/bin/gdal-config'
Now your compilation and linking command becomes the following one:
g++ `gdal-config --cflags` geofragc.cpp `gdal-config --libs` `gdal-config --dep-libs`
You have to use the g++ compiler to link with C++-built libraries.
Another option is to create a Makefile with these lines:
CXXFLAGS += ${shell gdal-config --cflags}
LDLIBS += ${shell gdal-config --libs}
LDLIBS += ${shell gdal-config --dep-libs}
geofragc: geofragc.cpp
and just call make with this Makefile.
I hope, it'll help.

How to build Static Binary for Tesseract?

I am currently building Tesseract 4.0.0 from source (on Ubuntu 14.04 for context), using the instructions found on: https://github.com/tesseract-ocr/tesseract/wiki/Compiling
I am using the following ./configure parameters:
./configure --disable-openmp --disable-graphics --disable-opencl --enable-static LDFLAGS='-static -static-libgcc -static-libstdc++' --disable-shared
Followed by
make and sudo make install
The compiled binary I am running after is src/api/tesseract, which works as intended. The problem is that when I run ldd on this file, it actually shows dependencies.
Am I looking in the wrong spot for the static binary of Tesseract (I ran a find command in the entire repo and didn't see anything else that looked like an executable), or am I misunderstanding the meaning of a static binary - I am under the impression it is pretty much an executable version of Tesseract that does not require any dependencies to be pre installed.
If there is any problem with the configure options too please let me know. I do not believe that --disable-openmp --disable-graphics --disable-opencl impacts static vs shared linking but I am using those for my desired tesseract build so I included them for more context.
$ uname -a
Linux vm00 4.15.0-50-generic #54-Ubuntu SMP Mon May 6 18:46:08 UTC
2019 x86_64 x86_64 x86_64 GNU/Linux
$ echo $CFLAGS
-static
$ echo $LDFLAGS
-static -static-libgcc -static-libstdc++
$ ./configure --enable-static LDFLAGS='-static -static-libgcc -static-libstdc++' --disable-shared
...
Configuration is done.
$ make
...
Making all in unittest
...
$ file src/api/tesseract
src/api/tesseract: ELF 64-bit LSB shared object, x86-64, version 1
(GNU/Linux), dynamically linked, interpreter /lib64/l, for
GNU/Linux 3.2.0,
BuildID[sha1]=96afb1f1ff8962b3f9046c40407364ebf26369d1, with
debug_info, not stripped
Not statically linked.

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

Compiling with -static-libgcc -static-libstdc++ still results in dynamic dependency on libc.so

I'm trying to make an executable that's as portable as possible. After removing a few dependencies, I came across the following when running the binary on another system:
/lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.15' not found (required by foob)
/lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.15' not found (required by foob)
/lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.14' not found (required by foob)
I'd prefer my binary not to require the user to upgrade their version of libc, so I'd like to remove this dependency as well.
The linker flags that produced the above binary already included -static-libgcc -static-libstdc++. How come the binary still requires on the shared libc.so.6?
I tried adding the -static flag as well, however when I try to run that binary the result is very strange:
$ ls -l foob
-rwxr-xr-x 1 claudiu claudiu 13278191 Oct 10 13:03 foob
$ ./foob
bash: ./foob: No such file or directory
What to do?
EDIT:
$ file foob
foob: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=5adee9a598b9261a29f1c7b0ffdadcfc72197cd7, not stripped
$ strace -f ./foob
execve("./foob", ["./foob"], [/* 64 vars */]) = -1 ENOENT (No such file or directory)
write(2, "strace: exec: No such file or di"..., 40strace: exec: No such file or directory
) = 40
exit_group(1) = ?
+++ exited with 1 +++
Interestingly, if I ldd the version without -static, it has two less entries than the version with -static, namely:
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f4f420c1000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f4f41636000)
GNU libc is not designed to be statically linked. Important functions, e.g. gethostbyname and iconv, will malfunction or not work at all in a static binary. Arguably even worse, under some conditions a static binary will attempt to dynamically open and use libc.so.6, even though the whole point of static linkage is to avoid such dependencies.
You should compile your program against uClibc or musl libc instead.
(This has been true for at least 15 years.)
First be aware that static linking of libc might not improve portability of your program, as libc might depend on other parts of your system e.g. kernel version.
If you want to try complete static linking just using -static should the trick. Provided that there are static versions of all used libraries installed.
You can check if your program has only linked static libraries by using:
ldd binary_name
EDIT:
Another way that provides useful information for debugging this problem would be to add --verbose to your linker flags.

Install gcc 4.7 but cannot run program sucessfully

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)