Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

gcc - A static library with undefined symbols?

I'm trying to build a project using a static library, so that the binary can be used even if the library isn't installed. However, I get lots of errors about undefined symbols when I try to do so.

Looking at the library, I see it has tons of undefined symbols, even though it's a .a static lib:

nm - u /usr/local/lib/libthis.a
....
U EVP_DigestFinal_ex
U EVP_DigestInit_ex
U EVP_DigestUpdate
U EVP_MD_CTX_cleanup
U EVP_MD_CTX_init

Those seem to be from openssl; others seem to be from libbzip2; etc.

Questions: 1. Why does the static (.a) lib have dependencies on shared objects (e.g. libopenssl) that aren't statically compiled? 2. How do I solve this? Trying to manually add -lssl doesn't seem to work. How do I get the binary to compile and not have external dependcies?

like image 947
SRobertJames Avatar asked Nov 22 '15 02:11

SRobertJames


People also ask

Can a static library have unresolved symbols?

At link time, a static library can have unresolved symbols in it, as long as you don't need the unresolved symbols, and you don't need any symbol that is in a .o file that contains an unresolved symbol.

Can a static library use a dynamic library?

Yes for instance when you call windows functions from within your static lib they are normally from some dynamic library so there should be no difference.

Why do we need shared libraries in addition to static ones?

The most significant advantage of shared libraries is that there is only one copy of code loaded in memory, no matter how many processes are using the library. For static libraries each process gets its own copy of the code.

What is GCC static?

The -static option links a program statically, in other words it does not require a dependency on dynamic libraries at runtime in order to run. To achieve static linking requires that the archive ( . a ) versions of your libraries exist on the system. so /usr/lib/libc.


1 Answers

Why does the static (.a) lib have dependencies on shared objects (e.g. libopenssl) that aren't statically compiled?

Just about every static library that you can build will have unresolved symbols, e.g.

int my_open_for_read(const char *filename)
{
  return open(filename, O_RDONLY);  // unresolved reference to open
}

As Marc Glisse pointed out, this a plain unresolved symbol, not a dependency on libc.so.

  1. How do I solve this?

There is no problem to solve here. When you link your binary, you get to decide which libraries to link statically, and which to link dynamically.

Trying to manually add -lssl doesn't seem to work.

This should work:

gcc main.o -lthis -lssl

Possibly you did something like

gcc main.o -lssl -lthis

which is wrong: the order of libraries on the link line matters.

How do I get the binary to compile and not have external dependcies?

Most OSes support using fully-static binaries. Generally this should not be your goal: it makes for less portable binaries, and their use is strongly discouraged.

If you really do want to produce a fully-static binary, link it with -static flag.

Why do you say full static is less portable?

Because they are.

if the user doesn't have the exact same build of the lib, the binary won't be portable with shared libs, but will be portable with static.

This is incorrect: most shared libraries support backward compatibility, e.g. libc.so.6 version 2.22 will happily run executables linked against version 2.3.6 from 10 years ago.

If you do ldd firefox

You need to pay attention to what you are doing:

file -L `which /usr/bin/firefox`
/usr/bin/firefox: POSIX shell script, ASCII text executable

If you look inside the shell script, you'll discover that it invokes /usr/lib/firefox/firefox, and that binary is dynamically linked:

ldd /usr/lib/firefox/firefox
    linux-vdso.so.1 =>  (0x00007ffca278d000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f511731b000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f5117117000)
    libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f5116e13000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f5116b0d000)
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f51168f7000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5116532000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f5117757000)
like image 181
Employed Russian Avatar answered Oct 09 '22 23:10

Employed Russian