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

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.

Related

Cross compilation for gpsd shows "unrecognized option"

I am cross-compiling gpsd3.20 on my Ubuntu 16.04 for the ARM architecture. As you may know, gpsd uses Sconsctruct to compile the source codes. During my cross-compilation, the moment when it needs to create the libgps.so it shows an error unrecognized option '-Wl, -Bsymbolic'.
Before posting the question here, I have tried t check my toolchain binaries and I found out that if I run this line manually:
sudo ./arm-v7a-linux-gnueabihf-ld -o test/gpsd-3.20/libgps.so.25.0.0 -pthread -shared -Wl,-Bsymbolic-functions -Wl,-soname=libgps.so.25 test/gpsd-3.20/os_compat.os test/gpsd-3.20/rtcm2_json.os test/rtcm3_json.os test/gpsd-3.20/shared_json.os test/gpsd-3.20/timespec_str.os test/gpsd-3.20/libgpsmm.os -L. -lrt -lm -lrt
The above commands print out the exact error as I mentioned previously. However, if I run the exact command replacing ld with gcc, then there is no any errors.
sudo ./arm-v7a-linux-gnueabihf-gcc -o test/gpsd-3.20/libgps.so.25.0.0 -pthread -shared -Wl,-Bsymbolic-functions -Wl,-soname=libgps.so.25 test/gpsd-3.20/os_compat.os test/gpsd-3.20/rtcm2_json.os test/rtcm3_json.os test/gpsd-3.20/shared_json.os test/gpsd-3.20/timespec_str.os test/gpsd-3.20/libgpsmm.os -L. -lrt -lm -lrt
Upon checking the arm-v7a-linux-gnueabihf-gcc --help, I found out that, gcc support -Wloptions whereas in the arm-v7a-linux-gnueabihf-ld it doesn't support the -Wl options. So now I am not sure how to change the SConstruct file so that it doesn't execute ld instead I want it to execute gcc especially for the libgps.so part.
(can't comment), so as answer: have you tried to set the env.-var.:
export LD=arm-v7a-linux-gnuabihf-gcc
Gcc takes -Wl,XXX and passes XXX to the linker.
I think you've got two combining problems here, though there's some guessing involved without looking into the build itself. First, scons shouldn't be adding the flag when building a library (https://github.com/SCons/scons/issues/3248 - fixed but, I believe, not part of a release). Second, "linking" should probably be done using gcc. If you call gcc to link, it still calls the linker behind the scenes - after dealing with options that are intended for gcc, which -Wl,-Bsymbolic is, it means pass -Bsymbolic on to the linking phase (indicated by -Wl, the 'l' meaning linker). So I'm supposing that the way you've told scons about the cross toolchain isn't quite right either, if it's calling ld directly you're probably going to have other issues as well.

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.

"multiple definition of `atexit'" when linking with DLL

I use MinGW32 more specifically TDM-GCC-32. I have very simple project I link to one custom library but this error pops out:
>g++ -D_WIN32 -D_MINGW -lgdi32 -lgdiplus -Linterception/x86 -linterception main.cpp -o interceptor.exe
interception/x86/libinterception.a(dgnes00125.o):(.text+0x0): multiple definitio
n of `atexit'
C:/TDM-GCC-32/bin/../lib/gcc/mingw32/5.1.0/../../../crt2.o:crt1.c:(.text+0x2c0):
first defined here
interception/x86/libinterception.a(dgnes00109.o):(.text+0x0): multiple definitio
n of `_onexit'
C:/TDM-GCC-32/bin/../lib/gcc/mingw32/5.1.0/../../../crt2.o:crt1.c:(.text+0x2d0):
first defined here
C:/TDM-GCC-32/bin/../lib/gcc/mingw32/5.1.0/../../../../mingw32/bin/ld.exe: C:/TD
M-GCC-32/bin/../lib/gcc/mingw32/5.1.0/../../../crt2.o: bad reloc address 0x20 in
section `.eh_frame'
collect2.exe: error: ld returned 1 exit status
Commands I use to build the library:
gcc -DINTERCEPTION_EXPORT -D_WIN32 -D_MINGW -shared -o interception.dll interception.c
dlltool -z interception.def --export-all-symbol interception.dll
dlltool -d interception.def -l libinterception.a
I guess I have to use different options for compiling the library to avoid redefinitions..
The dlltool method I believe is currently deprecated. I can't fault you here though, as most of the available documentation still says to do it this way.
Gcc will link directly against .dll files, making .a files obsolete (at least for dealing with dll's - the only current reason to use a .a file is for static linking). You don't even have to specify the dll with the -l flag, although you have to specify the path of the dll if it's not in your current directory
C:\Users\burito>gcc main.o opengl32.dll -o main.exe
gcc: error: opengl32.dll: No such file or directory
C:\Users\burito>gcc main.o c:\Windows\system32\opengl32.dll -o main.exe
C:\Users\burito>
Ok, opengl32.dll is perhaps not a great example, but I hope I've given you the general idea.
I believe MSVC still needs its .lib files to use a .dll, for which there are several ways of making them if the library doesn't come with one.
In your specific case, the command that should work would be...
g++ -D_WIN32 -D_MINGW -lgdi32 -lgdiplus interception/x86/interception.dll main.cpp -o interceptor.exe
If for whatever reason you really do need to create a .a file from a .dll, the command that has worked for me is...
gendef interception.dll
dlltool -l interception.a -d interception.def -k -A
As the repository you linked does provide .dll files in its releases, you shouldn't have to build them yourself

Executing cross-compiled C++ program using Boost on Raspberry Pi

I have built a GCC cross toolchain for the RPi and can cross-compile C++ source and successfully run it after copying the executable to the RPi.
Next I built the Boost libraries targeting ARM, using the cross toolchain. I can successfully build and link C++ source to those Boost libraries using the cross toolchain on my PC.
I then copied the program, dynamically linked to Boost, to the RPi and copied all built libraries into /usr/local/lib on the Pi. However, executing fails:
$ ./my_program
./my_program: error while loading shared libraries: libboost_system.so.1.60.0: cannot open shared object file: No such file or directory
Again, this library, libboost_system.so.1.60.0, exists in /usr/local/lib.
I also tried
export LD_LIBRARY_PATH='/usr/local/lib'
but that doesn't change anything. What am I doing wrong?
EDIT:
I build all source files like this (rpi-g++ is a symlink to my cross-compiler):
rpi-g++ -c -std=c++1y -Wall -Wextra -pedantic -O2 -I /path/to/cross/boost/include *.cpp
rpi-g++ -o myprog *.o -L /path/to/cross/boost/lib/ -lboost_system -pthread
EDIT 2:
When linked with
rpi-g++ -o myprog *.o -L /path/to/cross/boost/lib/ -rdynamic -lboost_system -pthread
the problem remains the same. I have checked and verified everything suggested by Technaton as well. Strangely, ldd insists that the created executable is "not a dynamic executable" (checked that on my PC and on the RPi), which doesn't make sense to me.
There are several things you can check. I've posted a complete check list here, but judging from your linker command line, number 5 is probably the culprit.
Check that your library and your program are correctly build for the target architecture. You can verify that by using file ./myprog and file libboost_system.so.1.60.0.
Make sure that you have copied the actual shared object, and not a link to it.
Ensure that the shared object file's permissions are sane (0755).
Run ldconfig -v and check that your shared object file is picked up. Normally, /usr/local/lib is in the standard library search path, and LD_LIBRARY_PATH is not required.
Make sure that your program is actually dynamically linked by running ldd ./myprog. Judging from your linker command line, that is the problem: You're missing -rdynamic.
Check the paths returned from ldd: If you have linked with rpath, the library search path might be screwed up. Try again without -rpath.

Ubuntu 11.10 linking perftools library

I can't get gcc in Ubuntu 11.10 to properly link in the google perftools -lprofiler.
The problem seems to be that the linker discards libraries which are not directly used in a program.
An example will help.
Let's call this main.cpp:
#include <math.h>
int main()
{
double value;
for (int i=0; i < 1000000; i++)
{
for (int j=0; j < 1000; j++)
value = sqrt(100.9);
}
return 0;
}
Compile using:
g++ -c main.cpp -o main.o
g++ main.o -o main -lm -lprofiler
Check the executable using ldd ./main:
linux-vdso.so.1 => (0x00007fff5a9ff000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f32bc1c9000)
/lib64/ld-linux-x86-64.so.2 (0x00007f32bc593000)
Normally, I would run:
CPUPROFILE=/tmp/profile ./main
to produce profile output. But since the profile library is not linked in no profile output is generated.
I've made sure the profiler library is in my search path, and have tried directly linking against the shared library and static library.
The above test works fine on Ubuntu 10.04, Ubuntu 10.10, Ubuntu 11.04, SUSE 12.1, and Fedora 16.
Also, once I include function calls that use the profiler (such as ProfilerStart() and ProfilerStop()), then the profiler library gets linked into the executable.
Any ideas on how to get gcc to link in the profiler library?
Thanks.
g++ main.o -o main -lm -lprofiler
As another.anon.coward commented, you are likely falling victim of your g++ using --as-needed linker flag. Try this instead:
g++ main.o -Wl,--no-as-needed -lprofiler -Wl,--as-needed
Notes:
g++ already adds -lm, no need to add it again
It is important to turn --as-needed back on. Not doing so will likely cause you to link to additional libraries that you don't really need.
In my case, the problem was that there was only a libprofiler.so.0, and no libprofiler.so in /usr/lib/:
user#compy:/usr/include$ dpkg -L libgoogle-perftools4
/.
/usr
/usr/share
/usr/share/doc
/usr/share/doc/libgoogle-perftools4
/usr/share/doc/libgoogle-perftools4/README.Debian
/usr/share/doc/libgoogle-perftools4/copyright
/usr/lib
/usr/lib/libprofiler.so.0.4.5
/usr/lib/libtcmalloc.so.4.2.6
/usr/lib/libtcmalloc_debug.so.4.2.6
/usr/lib/libtcmalloc_and_profiler.so.4.2.6
/usr/share/doc/libgoogle-perftools4/AUTHORS
/usr/share/doc/libgoogle-perftools4/TODO
/usr/share/doc/libgoogle-perftools4/README.gz
/usr/share/doc/libgoogle-perftools4/NEWS.gz
/usr/share/doc/libgoogle-perftools4/changelog.Debian.gz
/usr/lib/libtcmalloc.so.4
/usr/lib/libtcmalloc_and_profiler.so.4
/usr/lib/libprofiler.so.0
/usr/lib/libtcmalloc_debug.so.4
I don't know what the official fix to this is, but I simply created a symlink in /usr/lib:
user#compy:/usr/lib$ sudo ln -s libprofiler.so.0 libprofiler.so
This will make -lprofiler work.
If you don't mind changing your Makefile you can alternatively specify -l:libprofiler.so.0 instead of -lprofiler (note the extra colon) (source).
EDIT: The official way to get the .so is apparently to install the libgoogle-perftools-dev package as explained here:
user#compy:/usr/lib$ dpkg -S libprofiler.so
libgoogle-perftools-dev: /usr/lib/libprofiler.so
libgoogle-perftools4: /usr/lib/libprofiler.so.0.4.5
libgoogle-perftools4: /usr/lib/libprofiler.so.0
I understand that if you want to link to a certain lib, you should install the libx-dev package, which will contain the /usr/lib/libx.so. This file will only be a symlink to a specific version, such as /usr/lib/libx.so.1.2. When you link against /usr/lib/libx.so by specifying -lx to your linker, you will actually create a link in your program against the specific version linked at the time by recording a SONAME of libx.so.1 (the last version number is stripped as oulined here). So when you run your program at a later point in time the dynamic linker will look only for /usr/lib/libx.so.1, which is symlinked to /usr/lib/libx.so.1.2, and no /usr/lib/libx.so hence no dev package needs to exist.
So the libx-dev packages is for compiling and linking against libx, and the libx package is for running a precompiled program against libx.