http://www.hgesser.de/

Private Homepage von Hans-Georg Eßer

header

Navigation

Privates

Publikationen

Studium

Software

Vorlesungen

Online-Training

Sonstiges

Blaue Links: intern
Rote Links: extern


How to link a library statically?

(keywords: gcc, static link, statically linked, gcc -static fails)

When trying to compile a binary with a statically linked library I first read the gcc manpage, and it said:

   -static
       On systems that support dynamic linking, this prevents linking with the shared
       libraries.  On other systems, this option has no effect.

A website about Statically Linking X11R6.3 gave the further hint to put the libraries between -static and -dynamic. When starting with a command like

  gcc -o testprog testprog.c obj1.o obj2.o -llib1 -llib2 -llib3
and now wanting to statically link lib2 while keeping the other bindings dynamical, that would yield
  gcc -o testprog testprog.c obj1.o obj2.o -llib1 -static -llib2 -dynamic -llib3
However the tests I attempted with the tcptrack software (where I tried to statically link libpcap) were not successful but generated a compiler error -- while generating the binary with all libs bound dynamically was no problem.

Solution

The solution is as follows:

  1. In order to bind a library statically, first identify the .a file that belongs to the library, e.g. in case of libpcap and using the RPM package manager:
    $ rpm -ql libpcap|grep a$
    /usr/lib/libpcap.a  
    
  2. Now the .a file is an ar archive which contains object files. Create a new directory in the source tree, e.g. src/objects, change into the new directory and unpack the .a file with
    ar x ...path_to.../library.a
    
  3. Now compile your program in the standard way, e. g. with configure and make (do not execute make install). Observe what the last commands of the make step are -- in case of the tcptrack tool the last step was:
    g++  -g -O2  -pthread  -o tcptrack Collector.o main.o TCContainer.o TextUI.o PacketBuffer.o \
      Sniffer.o TCPConnection.o util.o SortedIterator.o IPv4Packet.o IPv4Address.o TCPPacket.o \
      NetworkPacket.o IPv4TCPPacket.o IPv4TCPCapture.o TCPTrack.o SocketPair4.o AppError.o PcapError.o \
      GenericError.o Guesser.o  -lrt -lpthread -lpcap -lncurses -lnsl -lnsl
    
    Here the bold part (-lpcap) must go, because this is the library that is to be linked statically. Instead the new object files must be added to the compiler call:
    g++ -g -O2  -pthread  -o tcptrack  objects/*.o  \
      Collector.o main.o TCContainer.o TextUI.o PacketBuffer.o \
      Sniffer.o TCPConnection.o util.o SortedIterator.o IPv4Packet.o IPv4Address.o TCPPacket.o \
      NetworkPacket.o IPv4TCPPacket.o IPv4TCPCapture.o TCPTrack.o SocketPair4.o AppError.o PcapError.o \
      GenericError.o Guesser.o -lrt -lpthread -lncurses -lnsl -lnsl
    
  4. That's it -- in this example, calling ldd tcptrack will prove that the new binary contains pcap and the loader won't try to dynamically bind it.

Questions? More information?

If someone can explain why the suggested -static fails, I'd add that piece of information to this page. If there's an easier way (e.g. without manually unpacking the .a file), I'd like to hear of it as well.

Improvements

[2014/02/28] Got a mail today from Florian Schüller which suggested the following improvement: "When using a makefile it is sufficient to add LDLIBS+=/usr/lib/library.a or simply /usr/lib/library.a after the *.c or *.o files -- that way it is not necessary to unpack the *.a file."


Copyright © 1997-2017 Hans-Georg Eßer; Server: Debian Linux, Apache Web Server, letzte Änderung: Friday, 28-Feb-2014 20:50:22 CET
Theme: Hazard Area 1.6 (modified), created by Bryan Bell, Copyright © 2000-2006 Weblogger.com.