Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When statically linking a library, getting Linker error : cannot find -lgcc_s

I want to statically link a library say libcurl. As both static and shared libraries are in same folder, I am using -Wl,-Bstatic to let the linker know to use static library.

g++ -o prog prog.o -Wl,-Bstatic -lcurl. 

But above command is giving error:

/usr/bin/ld: cannot find -lgcc_s

If I exclude -Wl,-Bstatic, it works fine, but It will use shared library which I dont want.

What is going wrong?

like image 801
aaa Avatar asked Jan 01 '23 23:01

aaa


1 Answers

When you use the g++ front-end to perform your linkage, like:

g++ -o prog prog.o -Wl,-Bstatic -lcurl

g++ invokes the linker passing it your linkage options and also silently adding to the linker commandline a large number of boiler-plate options that are invariant for C++ linkage.

For example, your C++ program very probably will need to link the standard C++ library, libstdc++, but your g++ command doesn't mention it. It certainly also needs the standard C library, but it isn't mentioned either. g++ automatically adds linkage options to link these and other libraries.

You can see all the boilerplate that g++ adds to your linkage by running it in verbose mode. You will see the like of:

$ g++ -v -o prog prog.o -Wl,-Bstatic -lcurl
...
...
COLLECT_GCC_OPTIONS='-v' '-o' 'prog' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
 /usr/lib/gcc/x86_64-linux-gnu/7/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/7/liblto_plugin.so \
 -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/7/lto-wrapper \
 -plugin-opt=-fresolution=/tmp/cckwrJp6.res -plugin-opt=-pass-through=-lgcc_s \
 -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc \
 -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc \
 --sysroot=/ --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu \
 --as-needed -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -z now -z relro \
 -o prog /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/Scrt1.o \
 /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crti.o \
 /usr/lib/gcc/x86_64-linux-gnu/7/crtbeginS.o \
 -L/usr/lib/gcc/x86_64-linux-gnu/7 -L/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu \
 -L/usr/lib/gcc/x86_64-linux-gnu/7/../../../../lib -L/lib/x86_64-linux-gnu \
 -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib \
 -L/usr/lib/gcc/x86_64-linux-gnu/7/../../.. prog.o \
 -Bstatic -lcurl -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc \     
 /usr/lib/gcc/x86_64-linux-gnu/7/crtendS.o \
 /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crtn.o
/usr/bin/x86_64-linux-gnu-ld: cannot find -lgcc_s
/usr/bin/x86_64-linux-gnu-ld: cannot find -lgcc_s
collect2: error: ld returned 1 exit status

Note in particular your -Bstatic option and the following linkage options:

 -Bstatic -lcurl -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc \     
 /usr/lib/gcc/x86_64-linux-gnu/7/crtendS.o \
 /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crtn.o

which include your -lcurl and also the default system libraries:

-lcurl -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc

Then see the documentation of the -Bstatic linker option:

-Bstatic

...

Do not link against shared libraries. This is only meaningful on platforms for which shared libraries are supported. The different variants of this option are for compatibility with various systems. You may use this option multiple times on the command line: it affects library searching for -l options which follow it. This option also implies --unresolved-symbols=report-all. This option can be used with -shared. Doing so means that a shared library is being created but that all of the library’s external references must be resolved by pulling in entries from static libraries.

[my emphasis]

So, your -Bstatic option directs the linker to link static versions of:

-lcurl -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc

It finds the static libcurl.a that you have installed. It fails to find a static library for -lgcc_s because there isn't any libgcc_s.a installed on your system. You just have dynamic versions of this and other basic system libraries, which is pretty normal.

If you want the linker to link static libraries only for the -l options that you specify, then you must turn on -Bstatic before your -l options and turn it off after them, -Bdynamic, even if this makes -Bdynamic the last thing on your commandline. Because g++ (or any other GCC front-end, gcc, gfortran...) is going to add -l options to your commandline behind the scenes. Link like:

g++ -o prog prog.o -Wl,-Bstatic -lcurl -Wl,-Bdynamic

to fix this particular linkage error.

like image 51
Mike Kinghan Avatar answered Jan 05 '23 15:01

Mike Kinghan