简体   繁体   中英

gcc static library linking vs dynamic linking

My build environment is CentOS 5 . I have a third party library called libcunit. I installed it with autotools and it generates both libcunit.a and libcunit.so . I have my own application that links with a bunch of shared libraries. libcunit.a is in the current directory and libcunit.so and other shared libraries are in /usr/local/lib/ . When I compile like:

gcc -o test test.c -L. libcunit.a -L/usr/local/lib -labc -lyz

I get a linkage error:

libcunit.a(Util.o): In function `CU_trim_left':
Util.c:(.text+0x346): undefined reference to `__ctype_b'
libcunit.a(Util.o): In function `CU_trim_right':
Util.c:(.text+0x3fd): undefined reference to `__ctype_b'

But when I compile with .so like:

gcc -o test test.c -L/usr/local/lib -lcunit -labc -lyz

it compiles fine and runs fine too.

Why is it giving error when linked statically with libcunit.a ?

Why is it giving error when linked statically with libcunit.a

The problem is that your libcunit.a was built on an ancient Linux system, and depends on symbols which have been removed from libc (these symbols were used in glibc-2.2 , and were removed from glibc-2.3 over 10 years ago). More exactly, these symbols have been hidden . They are made available for dynamic linking to old binaries (such as libcunit.so ) but no new code can statically link to them (you can't create a new executable or shared library that references them).

You can observe this like so:

readelf -Ws /lib/x86_64-linux-gnu/libc.so.6 | egrep '\W__ctype_b\W'
   769: 00000000003b9130     8 OBJECT  GLOBAL DEFAULT   31 __ctype_b@GLIBC_2.2.5

readelf -Ws /usr/lib/x86_64-linux-gnu/libc.a | egrep '\W__ctype_b\W'
# no output

Didn't notice that the libcunit.a is actually found in your case and the problem with linakge is rather in the CUnit library itself. Employed Russian is absolutely right, and he's not talking about precompiled binary here. We understand that you've built it yourself. However, CUinit itself seems to be relying on the symbol from glibc which is not available for static linking anymore. As a result you have only 2 options:

  1. File a report to the developers of CUnit about this and ask them to fix it;
  2. Use dynamic linking.

Nevertheless, my recommendation about your style of static linkage still applies. -L. is in general bad practice . CUnit is a 3rd party library and should not be placed into the directory containing source files of your project. It should be rather installed in the same way as the dynamic version, ie like you have libcunit.so in /usr/local/lib . If you'd supply prefix to Autotools on the configure stage of CUnit, then Autotools would install everything properly. So if you want to link statically with CUnit, consider doing it in the following form:

gcc -o test test.c -L/usr/local/lib -Wl,-Bstatic -lcunit -Wl,-Bdynamic -labc -lyz

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM