C - Compile static file - c

I want to compile C code into one monolithic executable file (include every dependencies in this file) using GCC.
Usually I can compile the code with this command:
gcc -o server ex-serv-x509.c -lgnutls
But when I try to compile it with this -static argument I get this error:
[root#localhost test]# gcc -static -o server ex-serv-x509.c -lgnutls
/usr/bin/ld: cannot find -lc
collect2: ld returned 1 exit status
[root#localhost test]#
How I can solve the problem?
Best wishes

Try using the ldd command to see what it's linking in without the -static option. Here's what I get for a silly program I have.
~$ gcc so.o -lm -o so
~$ ldd so
linux-gate.so.1 => (0x00db7000)
libm.so.6 => /lib/libm.so.6 (0x00c7f000)
libc.so.6 => /lib/libc.so.6 (0x0037f000)
/lib/ld-linux.so.2 (0x002da000)
~$ gcc so.o -static -lm -o so
~$ ldd so
not a dynamic executable
So without the static I automagically get the shared version of libc, which surprised me even though it should not have. I imagine you have the shared version but not the static, so you'll need to get the static library from somewhere if you have decided that 1986 is the year for you :-).
To make sure you can do: gcc -print-search-dirs and search through them and make sure that libc.a is not to be found.

Related

Completely static linking with clang

How can I generate completely static binaries with clang? I have used the following command:
clang -flto <source files> -o <executable output> -fuse-ld=lld -static-libgcc -lc -Bstatic -m32
And yet, the generated output depends on a certain .so file:
$ ldd <executable output file>
linux-gate.so.1 => (0xf77dd000)
libc.so.6 => /lib/libc.so.6 (0xf75f0000)
/lib/ld-linux.so.2 (0x5663b000)
The following answer tries to answer the question but doesn't directly address the problem.
Is it even possible, to generate completely independent binaries? Or should I have resort to using other different C library implementations other than libgcc?
If yes, then how do I link it with clang if I have the source code, of for example newlib?
Just compile it using the clang's -static flag.
On your case, try:
clang -flto <source files> -o <executable output> -static -m32
The results on my test program show:
[root#interserver ogrerobot.com]# ldd ./CppUtilsSpikes
not a dynamic executable

How to build a Shared Library but use static glibc on Linux?

I'm trying to create a shared library on centos using gcc 4.8.2
shared library code:
//reload.c
int func(int num){
return num++;
}
link command:
gcc -fPIC -shared reload.c -o reload.so
use ldd command:
linux-vdso.so.1 => (0x00007ffe6aa93000)
libc.so.6 => /usr/lib64/libc.so.6 (0x00007f27feb97000)
/lib64/ld-linux-x86-64.so.2 (0x00007f27ff169000)
Now, Want to statically link glibc, how to write it?
like it:
ldd xxx.so
not a dynamic executable
I tried the build options, but the error.
gcc -fPIC -shared reload.c -o reload.so -Wl,-Bstatic -lc
/usr/bin/ld: cannot find -lgcc_s
/usr/bin/ld: cannot find -lgcc_s
collect2: error: ld returned 1 exit status
thank you very much
You do not have dependencies to glibc at all for your code above, so the easiest way is to compile with the flag -nostdlib:
$ gcc -fPIC -shared reload.c -o reload.so -nostdlib
$ ldd reload.so
statically linked

Linking partially static and partially dynamic in GCC

I'm trying to compile a very simple (as simple as hello world) C program using both dynamic and static linking with GCC. I want to know how to do this in general, so my minimal test example is simply trying to link libc as static and libm dynamically.
I've come across at least the following other questions regarding the same topic:
GCC: static linking only some libraries
Static link of shared library function in gcc
Some of the answers therein suggest things such as using -Wl,-Bstatic and -Wl,-Bdynamic to specify which libraries are respectively static and dynamic. Also suggested is among others simply specifying the full path of the static library to link against.
I've tried several of these suggestions, and variants thereof. I don't understand the error message it gives me. I know what PIE is, but I don't see how it relates to what I'm trying to do.
Here are some failed attempts:
$ gcc test.c /usr/lib64/libc.a
linux-gnu/4.7.3/../../../../x86_64-pc-linux-gnu/bin/ld: dynamic STT_GNU_IFUNC symbol `strcmp' with pointer equality in `/usr/lib64/libc.a(strcmp.o)' can not be used when making an executable; recompile with -fPIE and relink with -pie
urned 1 exit status
$ gcc test.c -Wl,-Bdynamic -lm -Wl,-Bstatic -lc
/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../x86_64-pc-linux-gnu/bin/ld: cannot find -lgcc_s
/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../x86_64-pc-linux-gnu/bin/ld: cannot find -lgcc_s
collect2: error: ld returned 1 exit status
$ gcc -Wl,-Bdynamic -lm -Wl,-Bstatic -lc test.c
/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../x86_64-pc-linux-gnu/bin/ld: cannot find -lgcc_s
/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../x86_64-pc-linux-gnu/bin/ld: cannot find -lgcc_s
collect2: error: ld returned 1 exit status
$ gcc -Wl,-Bstatic -lc -Wl,-Bdynamic -lm test.c
/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../x86_64-pc-linux-gnu/bin/ld: dynamic STT_GNU_IFUNC symbol `strcmp' with pointer equality in `/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../lib64/libc.a(strcmp.o)' can not be used when making an executable; recompile with -fPIE and relink with -pie
collect2: error: ld returned 1 exit status
Compiling just with no arguments, and with -static work fine, but I need partial static compilation:
$ gcc test.c -lm
$ gcc -static test.c -lm
However, the following fails too:
$ gcc test.c /usr/lib64/libc.a /usr/lib64/libm.a
I've come across a similar error in this post:
C++ Statically linked shared library
However the answers do not seem to apply to my problem.
The program I'm trying to compile is simply (as test.c):
#include <stdio.h>
#include <math.h>
int main(int argc, char **argv)
{
int i = 0;
for(i = 0; i < 65535; i++) {
printf("%f\n", sinf(i));
printf("%f\n", cosf(i));
printf("%f\n", tanf(i));
printf("%f\n", sqrtf(i));
}
return 0;
}
EDIT: Please note that the program must be complex enough to actually require libm, otherwise linking attempts might give false positives if libm is not really needed. In my original test.c example, I used only sinf() to a constant value, which made the compiler optimize out the sinf() call completely.
I'm using:
$ gcc --version
gcc (Gentoo 4.7.3-r1 p1.4, pie-0.5.5) 4.7.3
The following worked for me
ln -s `gcc -print-file-name=libc.a`
gcc -static-libgcc -L. -lc test.c
Then ldd a.out gives:
not a dynamic executable
Edit:
The OP wants to link one library dynamically and another statically. He have the example of linking libc statically and libm dynamically. That particular case I have not been able to achieve. However, the opposite is possible i.e. linking libc dynamically and libm statically.
ln -s `gcc -print-file-name=libm.a`
gcc test.c -L. -lm
then ldd a.out gives
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0x41960000)
/lib/ld-linux.so.2 (0x4193d000)
Note that the link order matters.e.g gcc -L. -lm test.c does not work.
This works with other libraries as well. For example gomp
gcc -fopenmp test.c
ldd shows libgomp.so.1. We can link it statically like this
ln -s `gcc -print-file-name=libgomp.a`
gcc -L. -fopenmp test.c
Now ldd a.out does not show libgomp.so.1. But in this case pthreads is still linked dynamically. To link pthreads statically requires that libc be linked statically as well.

Linux linking a shared object

I am linking an so, that depends on libmxml.so. However I have no rights install libmxml.so.
So thats what I am doing
gcc -shared -m32 -o ServiceProvider.so ServiceProvider.o -L ../../../../system/addonlibs/ -lmxml -lpthread
ldd shows me
ldd ServiceProvider.so
libmxml.so.1 => not found
libpthread.so.0 => /lib/libpthread.so.0 (0x40026000)
libc.so.6 => /lib/libc.so.6 (0x40046000)
the second try was
gcc -shared -m32 -o ServiceProvider.so ServiceProvider.o ../../../../system/addonlibs/libmxml.so -lpthread
and still ldd shows me
ldd ServiceProvider.so
libmxml.so.1 => not found
libpthread.so.0 => /lib/libpthread.so.0 (0x40026000)
libc.so.6 => /lib/libc.so.6 (0x40046000)
Consequently, ldd does not find the library, since I only have "libmxml.so", but no "libmxml.so.1". How do I get rid of this ".1" suffix? Why is it comming?
When you link with a dynamic library, you should not do :
gcc -shared -m32 -o ServiceProvider.so ServiceProvider.o ../../../../system/addonlibs/libmxml.so -lpthread
Instead, make sure that /yourpath/system/addonlibs (you should use the full path instead of a relative one) is in you LIBRARY_PATH. Then change you link command.
export LIBRARY_PATH=/yourpath/system/addonlibs:$LIBRARY_PATH
gcc -shared -m32 -o ServiceProvider.so ServiceProvider.o -lmxml -lpthread
You can also write that:
gcc -shared -m32 -o ServiceProvider.so ServiceProvider.o -L/yourpath/system/addonlibs -lmxml -lpthread
However, to run your program, you will need to have your library path in LD_LIBRARY_PATH.
If you have issues with .soand .so.1 stuff, then rename your .so to .so.1 and make a symlink from .so.1 to .so.
Edit:
If you do objdump -p libmxml.so | grep SONAME you will probably get libmxml.so.1.
It is where you get the libmxml.so.1 identifier.

Can two different versions of the same libs (with same name) exists in an application?

I have some scenario like this:
Product-> Platform-> mylibs(version-1)
Product-> mylibs(version-2)
i.e Product uses mylibs (version-2) directly. Product also uses platform (which is also a dynamic lib) and platform uses my libs (version-1).
The names of the libs used by product and platform are same. Only versions are different and both these versions are not compatible.
Is there a way with ".so" libs in linux that Platform can link to one version and product can link to another version of the same libs having the same name?
Note, even changing the names of the libs won't be enough by default, as symbol names would conflict.
Your libs should use soname and versioned symbols, in which case they can even be called the same.
$ make
gcc -shared -fpic -Wl,-soname -Wl,libmylibs.so.1 -Wl,--default-symver -o libmylibs.so.1 mylibs1.c
gcc -shared -fpic -Wl,-soname -Wl,libmylibs.so.2 -Wl,--default-symver -o libmylibs.so.2 mylibs2.c
gcc -shared -fpic -Wl,-soname -Wl,libplatform.so.1 -Wl,--default-symver -Wl,--default-imported-symver -o libplatform.so.1 platform.c libmylibs.so.1
gcc -Wl,-rpath-link -Wl,. -Wl,--default-imported-symver -o program program.c libplatform.so.1 libmylibs.so.2
/usr/bin/ld: warning: libmylibs.so.1, needed by libplatform.so.1, may conflict with libmylibs.so.2
$ LD_LIBRARY_PATH=$PWD ldd ./program
linux-vdso.so.1 => (0x00007fff1e3ff000)
libplatform.so.1 => /tmp/so-4539442/libplatform.so.1 (0x00007f6dc3ba0000)
libmylibs.so.2 => /tmp/so-4539442/libmylibs.so.2 (0x00007f6dc399f000)
libc.so.6 => /lib/libc.so.6 (0x00007f6dc364c000)
libmylibs.so.1 => /tmp/so-4539442/libmylibs.so.1 (0x00007f6dc344b000)
/lib64/ld-linux-x86-64.so.2 (0x00007f6dc3da1000)
$ LD_LIBRARY_PATH=$PWD ./program
lib version 2, platform lib version 1

Resources