gcc - A static library with undefined symbols?

17,091

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)
Share:
17,091
SRobertJames
Author by

SRobertJames

Updated on June 05, 2022

Comments

  • SRobertJames
    SRobertJames almost 2 years

    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?

  • SRobertJames
    SRobertJames over 8 years
    Thanks. Why do you say full static is less portable? Since Linux uses .so and not DLLs, 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. If you do ldd firefox, for example, you'll see it's fully static - how else can you have a portable binary on Linux?
  • SRobertJames
    SRobertJames over 8 years
    Nice update, especially catching the firefox script! But the libs ldd shows are all the system libs, which I know a) can't be be static and b) are usually backwards compatible. My points still stand for non-system libs (eg zlib ssl and dozens more) ; notice that firefox uses those static, which I believe is the only portable way to do so
  • Employed Russian
    Employed Russian over 8 years
    @SRobertJames I only argued against fully-static binaries. Linking in non-system libraries statically is fine, so long as you continue to use system libraries dynamically. A literal reading of your question: "How to ... not have external dependcies" implies fully-static linking.
  • qweruiop
    qweruiop over 7 years
    @SRobertJames Your point regarding using non-static system libraries is a very good one.