The problem, as I understand it, is as follows. You have several libraries, some static, some dynamic, and some both static and dynamic. gcc 's default behavior is a "mostly dynamic" link. That is, gcc links to dynamic libraries when possible, but otherwise returns to static libraries. When you use the -static option for gcc , the behavior should only link static libraries and fail if a static library is not found, even if there is a corresponding dynamic library.
Another option that I have repeatedly wanted to have gcc is what I call -mostly-static and is essentially the opposite of -dynamic (default). -mostly-static , if one exists, prefers to reference static libraries, but returns to dynamic libraries.
This option does not exist, but it can be emulated with the following algorithm:
Building command line links without static output.
Iterate over dynamic link parameters.
Accumulate library paths, i.e. these form parameters -L <lib_dir> in the variable <lib_path>
For each dynamic link option, that is, for forms -l <lib_name> , run the command gcc <lib_path> -print-file-name = lib <lib_name> .a and capture the output.
If the command prints something other than what you passed, it will be the full path to the static library. Replace the dynamic library parameter with the full path to the static library.
Rinse and repeat until you have processed the entire communication command line. Optionally, the script can also accept a list of library names to exclude from a static link.
The following bash script seems to do the trick:
#!/bin/bash if [ $# -eq 0 ]; then echo "Usage: $0 [--exclude <lib_name>]. . . <link_command>" fi exclude=() lib_path=() while [ $# -ne 0 ]; do case "$1" in -L*) if [ "$1" == -L ]; then shift LPATH="-L$1" else LPATH="$1" fi lib_path+=("$LPATH") echo -n "\"$LPATH\" " ;; -l*) NAME="$(echo $1 | sed 's/-l\(.*\)/\1/')" if echo "${exclude[@]}" | grep " $NAME " >/dev/null; then echo -n "$1 " else LIB="$(gcc $lib_path -print-file-name=lib"$NAME".a)" if [ "$LIB" == lib"$NAME".a ]; then echo -n "$1 " else echo -n "\"$LIB\" " fi fi ;; --exclude) shift exclude+=(" $1 ") ;; *) echo -n "$1 " esac shift done echo
For example:
mostlyStatic gcc -o test test.c -ldl -lpthread
on my system returns:
gcc -o test test.c "/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/libdl.a" "/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/libpthread.a"
or with the exception of:
mostlyStatic --exclude dl gcc -o test test.c -ldl -lpthread
Then I get:
gcc -o test test.c -ldl "/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/libpthread.a"
jcoffland Dec 6 2018-12-12T00: 00Z
source share