Originally published 27 August 2012, updated 5 November 2019 (move to Jekyll, add the self-contained exmample and link to Repl.it)

When distributing binary executable or libraries it is sometimes desirable to link some of their dependencies statically while it may be more efficient to link some of the other dependencies dynamically. For example, we have recently been doing a fair amount of cross-compilation from Linux to Windows using mingw32 and prefer to statically link in the Boost libraries while leaving the standard Windows libraries dynamically linked.

Fortunately GNU ld and gcc support a very simple syntax for doing this sort of mixed linking: it is possible to specify multiple -static and -shared options on the command line. All libraries specified after -static and before any further -shared options will statically linked in. Conversely all libraries specified after -shared and before any -static will be dynamically linked. From the man page for ld(1):

-static

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.

Note you need to use -Wl, to pass linker options from GCC commandline.

Here is a self-contained example:

# Create the source code files
echo "int a(void) {return 2;} " > a.c
echo "int b(void) {return 3;} " > b.c
# Prototypes are included straight into the .c file
echo "int a(void); int b(void); int c(void) {return a()+b();}; " > c.c

# This will be application
echo "int c(void);  int main(void) {return c();}; " > d.c

# NB compilation must be with -fPIC
gcc a.c -shared -o liba.so
gcc b.c -shared -o libb.so
gcc -fPIC  -c a.c -o a.o
ar rcs liba.a a.o
gcc -fPIC  -c b.c -o b.o
ar rcs libb.a b.o
gcc -fPIC -c c.c -o c.o

# Create the mixed static/shared library
gcc -nostdlib -shared  -o libbnc2.so   -L.  c.o    -lb  -Wl,-static -la  

# Create the application
gcc -L.  d.c -o d -lbnc2 -lb 

# Test out
echo "Trying to execute the program: "
LD_LIBRARY_PATH=. ./d
echo "Returned: $?"

You can try it at Repl.It