static links only to some libraries

How can I statically link only some specific libraries to my binary when linking to GCC?

gcc ... -static ... tries to statically link all the linked libraries, but I don't have a static version of some of them (ex: libX11).

+90
gcc linker static-libraries
Nov 11 2018-10-11
source share
8 answers

gcc -lsome_dynamic_lib code.c some_static_lib.a

+96
Nov 11 2018-10-11
source share

You can also use the ld -Bdynamic option

 gcc <objectfiles> -static -lstatic1 -lstatic2 -Wl,-Bdynamic -ldynamic1 -ldynamic2 

All libraries after it (including system libraries linked by gcc automatically) will be linked dynamically.

+42
Nov 15 '10 at 12:20
source share
 gcc objectfiles -o program -Wl,-Bstatic -ls1 -ls2 -Wl,-Bdynamic -ld1 -ld2 

you can also use the -static-libgcc -static-libstdc++ flags for gcc libraries

remember that if libs1.so and libs1.a , the linker will select libs1.so if it is before -Wl,-Bstatic or after -Wl,-Bdynamic . Remember to pass -L/libs1-library-location/ before calling -ls1 .

+26
Jul 18 '13 at 1:06 on
source share

From manpage ld (this does not work with gcc), referring to the --static option:

You can use this option several times on the command line: this affects the library that looks for the -l options that follow it.

One solution is to place your dynamic dependencies before the --static on the command line.

Another possibility is not to use --static , but instead provide the full file name / path for the file of the static object (i.e. do not use -l) to statically bind a specific library. Example:

 # echo "int main() {}" > test.cpp # c++ test.cpp /usr/lib/libX11.a # ldd a.out linux-vdso.so.1 => (0x00007fff385cc000) libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00007f9a5b233000) libm.so.6 => /lib/libm.so.6 (0x00007f9a5afb0000) libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00007f9a5ad99000) libc.so.6 => /lib/libc.so.6 (0x00007f9a5aa46000) /lib64/ld-linux-x86-64.so.2 (0x00007f9a5b53f000) 

As you can see in the example, libX11 not included in the list of dynamically linked libraries, since it was linked statically.

Beware: the .so file is always linked dynamically, even if specified with the full file / path name.

+25
Nov 11 '10 at 15:40
source share

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" 
+17
Dec 6
source share

Some boot loaders (linkers) provide switches to enable or disable dynamic loading. If GCC runs on such a system (Solaris - and possibly others), you can use the appropriate option.

If you know which libraries you want to link statically, you can simply specify the static library file in the link line β€” the full path.

+4
Nov 11 2018-10-11
source share

There is also the -l:libstatic1.a option -l:libstatic1.a (minus one colon) of the -l option in gcc, which can be used to link the static library (thanks to https://stackoverflow.com/a/960919/ ), Documented? Not in gcc official documentation (which is also not accurate for shared libs): https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html

 -llibrary -l library 

Look for a library named library when linking. (The second alternative, with the library as a separate argument, is for POSIX compliance only and is not recommended.) ... The only difference between using the -l option and specifying the file name is that -l surrounds the library with lib and '. a and searches for multiple directories.

This file describes binutils ld doc. The -lname option will search libname.so and then libname.a will add the lib prefix and .so (if it is currently enabled) or the suffix .a . But the -l:name parameter will only search for the specified name: https://sourceware.org/binutils/docs/ld/Options.html

 -l namespec --library=namespec 

Add the archive or object file specified by namespec to the list of files for communication. This option can be used any number of times. If namespec looks like :filename , ld will look for the library path for the file named filename , otherwise it will look for the library path for the file named libnamespec.a .

On systems that support shared libraries, ld can also look for files other than libnamespec.a . In particular, on ELF and SunOS systems, ld will search for a directory for a library called libnamespec.so before searching for one of them called libnamespec.a . (From the convention, the .so extension points to a shared library.) Note that this behavior does not apply to :filename , which always indicates a file named filename .

Linkers will search the archive only once, in the place where it is specified on the command line. If the archive defines a character that was undefined in some object that appeared before the archive on the command line, the linker will contain the corresponding file from the archive. However, the undefined character in an object that appears later on the command line will not call the linker to search the archive again.

See the -( option -( to force the linker to search for archives several times.

You can specify the same archive several times on the command line.

This type of archive search is standard for Unix linkers. However, if you use ld on AIX, note that it is different from the behavior of the AIX linker.

The -l:namespec option -l:namespec documented since binusils version 2.18 (2007): https://sourceware.org/binutils/docs-2.18/ld/Options.html

+4
May 24 '17 at 16:50
source share

in order to link the dynamic and static library in one line, you must put the static libraries after the dynamic libraries and object files, for example:

gcc -lssl main.o -lFooLib -o main

otherwise it will not work. I sometimes need to understand this.

+1
Nov 02 '17 at 0:07
source share



All Articles