Linux link static lib

static linking only some libraries

How can I statically link only a some specific libraries to my binary when linking with GCC? gcc . -static . tries to statically link all the linked libraries, but I haven’t got the static version of some of them (eg: libX11).

8 Answers 8

gcc -lsome_dynamic_lib code.c some_static_lib.a

Link libraries after object files — especially static libraries. In ancient and modern versions of the link environment (I’m not sure of the status quo for modestly old versions as of November 2010), listing the static library before the code.c file guarantees that the symbols in it will be ignored unless there happens to be a main() function in one of the library object files.

@jb by default, gcc links dynamically. When you use -lsome_dynamic_lib it gets linked dynamically as expected. But, when gcc is given a static library explicitly, it will always try to link it statically. There are, however, some tricky details about the order in which symbols get resolved; I’m not quite sure how that works. I’ve learned that, when in doubt, try rearranging the order of library flags 🙂

You could also use ld option -Bdynamic

gcc -static -lstatic1 -lstatic2 -Wl,-Bdynamic -ldynamic1 -ldynamic2 

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

-Wl,-Bdynamic requires GNU ld, so this solution doesn’t work on systems where gcc uses the system ld (e.g. Mac OS X).

gcc objectfiles -o program -Wl,-Bstatic -ls1 -ls2 -Wl,-Bdynamic -ld1 -ld2 

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

keep in mind that if libs1.so and libs1.a both exists, the linker will pick libs1.so if it’s before -Wl,-Bstatic or after -Wl,-Bdynamic . Don’t forget to pass -L/libs1-library-location/ before calling -ls1 .

This works well for me, while using -static somewhere in the command fails (I assume it tries to link more things statically than only the libraries I want).

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

You may use this option multiple times on the command line: it affects library searching for -l options which follow it.

One solution is to put your dynamic dependencies before the —static option on the command line.

Another possibility is to not use —static , but instead provide the full filename/path of the static object file (i.e. not using -l option) for statically linking in of 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 is not in the list of dynamically-linked libraries, as it was linked statically.

Читайте также:  Сложно ли установить линукс

Beware: An .so file is always linked dynamically, even when specified with a full filename/path.

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 to link «mostly dynamic». That is, gcc links to dynamic libraries when possible but otherwise falls back to static libraries. When you use the -static option to gcc the behavior is to only link static libraries and exit with an error if no static library can be found, even if there is an appropriate dynamic library.

Another option, which I have on several occasions wished gcc had, is what I call -mostly-static and is essentially the opposite of -dynamic (the default). -mostly-static would, if it existed, prefer to link against static libraries but would fall back to dynamic libraries.

This option does not exist but it can be emulated with the following algorithm:

  1. Constructing the link command line with out including -static.
  2. Iterate over the dynamic link options.
  3. Accumulate library paths, i.e. those options of the form -L in a variable
  4. For each dynamic link option, i.e. those of the form -l , run the command gcc -print-file-name=lib.a and capture the output.
  5. If the command prints something other than what you passed, it will be the full path to the static library. Replace the dynamic library option with the full path to the static library.

Rinse and repeat until you’ve processed the entire link command line. Optionally the script can also take a list of library names to exclude from static linking.

The following bash script seems to do the trick:

#!/bin/bash if [ $# -eq 0 ]; then echo "Usage: $0 [--exclude ]. . . " 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 "$" | 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 
mostlyStatic gcc -o test test.c -ldl -lpthread 
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" 
mostlyStatic --exclude dl gcc -o test test.c -ldl -lpthread 
gcc -o test test.c -ldl "/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/libpthread.a" 

There is also -l:libstatic1.a (minus l colon) variant of -l option in gcc which can be used to link static library (Thanks to https://stackoverflow.com/a/20728782). Is it documented? Not in the official documentation of gcc (which is not exact for shared libs too): https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html

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

The binutils ld doc describes it. The -lname option will do search for libname.so then for libname.a adding lib prefix and .so (if enabled at the moment) or .a suffix. But -l:name option will only search exactly for the name specified: 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 to link. This option may be used any number of times. If namespec is of the form :filename , ld will search the library path for a file called filename , otherwise it will search the library path for a file called libnamespec.a .

On systems which support shared libraries, ld may also search for files other than libnamespec.a . Specifically, on ELF and SunOS systems, ld will search a directory for a library called libnamespec.so before searching for one called libnamespec.a . (By convention, a .so extension indicates a shared library.) Note that this behavior does not apply to :filename , which always specifies a file called filename .

The linker will search an archive only once, at the location where it is specified on the command line. If the archive defines a symbol which was undefined in some object which appeared before the archive on the command line, the linker will include the appropriate file(s) from the archive. However, an undefined symbol in an object appearing later on the command line will not cause the linker to search the archive again.

See the -( option for a way to force the linker to search archives multiple times.

You may list the same archive multiple times on the command line.

This type of archive searching is standard for Unix linkers. However, if you are using ld on AIX, note that it is different from the behaviour of the AIX linker.

Источник

Static Library

A static library is basically an archive (like a zip file) of object files, which are compiled from the .c/.cpp source code.

(The -c switch means: Compile and assemble, but do not link.)

Thus, we get two files test1.o and test2.o.

Now, we can use ar to put these object files together into a single static library.

ar rsv testlib.a test1.o test2.o

Now the testlib.a contains test1.o and test2.o.

gcc -o test.out test.c testlib.a

Alternatively, you could use the explicity linking options to link the static library (-L switch specifies the static library path and -l followed by the name of the static library):

gcc -o test.out test.c -L. -ltestlib

The static library is distributed with a function declaration header files .h, so that you know how to invoke them and the compiler takes care of them e.g. linking .a static libraries into your executables.

The Dynamic Link Library (DLL) is stored separately from the target application and shared among different applications, compared to Static Library. The DLL is the file extension on Windows while on Linux, it is *.so (Shared Object).

The .so/.dll can be loaded right before the application starts or during the application’s runtime. On Windows, the Win32 API LoadLibrary is used while on Linux gcc compiler, the dlopen function is used.

gcc -shared -o libhello.so -fPIC hello.c
g++ Application.cpp -o Application -I/home/wjw/dev/Youtube/OpenGL/Dependencies/GLFW/include -L/home/wjw/dev/Youtube/OpenGL/Dependencies/GLFW/lib -lglfw
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:~/dev/Youtube/OpenGL/Dependencies/GLFW/lib

Calling C++ Shared Library from Python Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// https://helloacm.com
extern «C»
{
// A function adding two integers and returning the result
int SampleAddInt(int i1, int i2)
{
return i1 + i2;
}

// A function doing nothing 😉
void SampleFunction1()
{
// insert code here
}

// A function always returning one
int SampleFunction2()
{
// insert code here

return 1;
}
}
g++ -Wall -O3 -shared TestLib.c -o TestLib.so
#!/usr/bin/python

import ctypes

def main():
TestLib = ctypes.cdll.LoadLibrary(‘/home/wjw/misc/cpp_static_dynamic_lib/TestLib.so’)
print(TestLib.SampleAddInt(1, 2))

if __name__ == ‘__main__’:
main()

Источник

Оцените статью
Adblock
detector