How to Force Linking with a Static Library When a Shared Library of Same Name Is Present

g++ linker: force static linking if static library exists?


g++ -Wl,-Bstatic -lz -lfoo -Wl,-Bdynamic -lbar -Wl,--as-needed

Will link zlib and libfoo as static, and libbar as dynamic . --as-needed will drop any unused dynamic library.

Link a static library to a shared one during build?

You need --whole-archive linker option in this case to command the linker to include whole static libs' content into the shared lib.

g++ -shared sample.o -o libSample.so -Wl,-whole-archive -lmylib1.a -lmylib2.a -Wl,-no-whole-archive

From man ld:

For each archive mentioned on the command line after the --whole-archive option, include every object file in the archive in the link, rather than searching the archive for the required object files. This is normally used to turn an archive file into a shared library, forcing every object to be included in the resulting shared library. This option may be used more than once.

Two notes when using this option from gcc: First, gcc doesn't know about this option, so you have to use -Wl,-whole-archive. Second, don't forget to use -Wl,-no-whole-archive after your list of archives, because gcc will add its own list of archives to your link and you may not want this flag to affect those as well.

how to force linker to use shared library instead of static library?

You could use -l option in its form -l:filename if your linker supports it (older versions of ld didn't)

gcc -o app app.o -L. -l:libtest.so

Other option is to use the filename directly without -l and -L

gcc -o app app.o /path/to/library/libtest.so

Linking a static library into a shared library without -fPIC

You cannot (or at least you should not) link a static library into a shared library.

Even if you happen to apparently succeed in linking a non-PIC static library libX.a into a shared library libY.so, the resulting thing won't have position-independent code (so would have a lot of "useless" or "annoying" relocations).

A shared library needs to contain only position-independent code (in practice); but a static library does not contain PIC.

I do not want to compile static.cpp with -fPIC

But you really should.

Read Drepper's How to Write Shared Libraries for details.

BTW, some Linux distributions (e.g. Debian) provide a libc6-pic package giving files such as /usr/lib/x86_64-linux-gnu/libc_pic.a which are a static library of position-independent code. This might be used to extend your system's libc.so.6 with e.g. your own function (or your own malloc, etc...).

In practice, you'll better recompile your static library code with -fPIC; BTW the x86-64 ISA was designed to facilitate PIC.

At last, if you care about optimizations, there are many of them. Did you consider compiling and linking with gcc -O3 -fPIC -flto ? In some cases, you might consider -ffast-math (which enables optimizations against the C standard), or replacing -O3 with -Ofast.

And you surely should use a recent GCC or Clang compiler (or a recent proprietary icc). This old question (mentioned in your comments) is about 4.7. Current GCC in fall 2018 is GCC 8, and GCC 9 is worked upon (so should appear in spring 2019). Current Clang is Clang 7.
Compilers are continuously making progress on optimizations.

You might want to download the source tarball of the latest release of GCC or of Clang and build that on your computer. This is a good way to have a recent version of these compilers, since distribution makers often prefer an older variant of them (which is compatible even with non-standard compliant code).

Shared library symbol conflicts and static linking (on Linux)


Is this a designed behavior?

Yes.

At the time of introduction of shared libraries on UNIX, the goal was to pretend that they work just as if the code was in a regular (archive) library.

Suppose you have foo() defined in both libfoo and libbar, and bar() in libbar calls foo().

The design goal was that cc main.c -lfoo -lbar works the same regardless of whether libfoo and libbar are archive or a shared libraries. The only way to achieve this is to have libbar.so use dynamic linking to resolve call from bar() to foo(), despite having a local version of foo().

This design makes it impossible to create a self-contained libbar.so -- its behavior (which functions it ends up calling) depends on what other functions are linked into the process. This is also the opposite of how Windows DLLs work.

Creating self-contained DSOs was not a consideration at the time, since UNIX was effectively open-source.

You can change the rules with special linker flags, such as -Bsymbolic. But the rules get complicated very quickly, and (since that isn't the default) you may encounter bugs in the linker or the runtime loader.

Proper way to link a static library using GCC

Thanks for the replies! Turns out the problem was due to link order. Apparently, if you use a library which in turn has other library dependencies, those other dependencies must be listed after the library, not before as I had been doing. Learned something new!



Related Topics



Leave a reply



Submit