Linking a Static Library into a Shared Library

how to link static library into dynamic library in gcc

Static libraries have special rules when it comes to linking. An object from the static library will only be added to the binary if the object provides an unresolved symbol.

On Linux, you can change that behavior with the --whole-archive linker option:

g++ -Wl,--whole-archive some_static_lib.a -Wl,--no-whole-archive

Linking a shared library against a static library: must the static library be compiled differently than if an application were linking it?

You do not have to use PIC code in shared objects (as you have discovered you can use the -mimpure-text option to allow that).

That said, non-PIC code in shared objects are more heavyweight. With PIC code, the text pages in memory are just direct memory mappings of the text pages on disk. This means that if multiple processes are using the shared object, they can share the memory page.

But if you do not have PIC code, when the runtime linker loads the shared object, it will have to apply fixups to the text pages. This means that every processes that uses the shared object will have it's own unique version of any text page that has a fixup on it (even if the shared object is loaded at the same address as copy-on-write only notices that the page was modified and not that it was modified in the same way).

To me, the important issue is whether you will simultaneously have multiple processes running that each load the shared object. If you do, it is definitely worth making sure all the code within the SO is PIC.

But if that is not the case and only a single process has the shared object loaded, it's not nearly as critical.

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).

Linking a Static library into a shared library

Do what the compiler suggests: Recompile with -fPIC

Explanation: Shared Objects have the requirement, that the addresses in their code do not depend on the memory layout of the binary image in address space. Statically linked code is not bound by this, all addresses in virtual address space are known at link time and hence the code is not required to cope with locations being not determined at compile time.

The -fPIC compiler flag enables compilation of Position Independent Code (PIC). The static libraries you're trying to link were not compiled as PIC that's why the linker complains. The solution is to recompile the static library with PIC enabled.


On a side note: PIC is also a fundamental for Address Space Layout Randomization (ASLR), a security measure with the goal of making the exploitation of vulnerable programs harder.

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.

Static link of shared library function in gcc

Refer to:

http://www.linuxquestions.org/questions/linux-newbie-8/forcing-static-linking-of-shared-libraries-696714/

You need the static version of the library to link it.

A shared library is actually an executable in a special format
with entry points specified (and some sticky addressing issues
included). It does not have all the information needed to
link statically.

You can't statically link a shared library (or dynamically link a static one).

The flag -static will force the linker to use static libraries (.a) instead of shared (.so) ones. But static libraries aren't always installed by default, so you may have to install the static library yourself.

Another possible approach is to use statifier or Ermine. Both tools take as input a dynamically linked executable and as output create a self-contained executable with all shared libraries embedded.

Can a C++ Static Library link to shared library?

Static libraries are not linked. They are just a collection of object files (*.obj or *.o) that are archived together into a library file (kind of like a tar/zip file) to make it easier for the linker to find the symbols it needs.

A static lib can call functions that are not defined (but are only declared in a header file), as it is only compiled. Then when you link an exe or dll that uses the static lib you will have to link with another library that provides the called from the static lib but not defined in it.

If you want to the linker to automatically link other libraries Stephen's suggestion will work and is used by very reputable libraries like boost and stlport. To do this put the pragma in the main header file for the static library. You should include the static library and its dependants.

However IMO this feature is really meant for library writers, where the library is in the system library path so the linker will easily find it. Also in the case of boost and stlport they use this feature to support multiple version of the same libraries with options defined with #defines where different options require different versions of the library to be linked. This means that users are less likely to configure boost one way and link with a library configured another.

My preference for application code is to explicitly link the required parts.

Multiple linking of a static library across different shared objects

What are the options to deal with this, given that I can't modify the third-party library?

Both you and the 3rd party developer have committed a sin -- you are exposing symbols from ipps.a in your own interface (this is the default on UNIX).

You should hide these symbols instead, using e.g. a linker version script. Example.

If you hide all the ipps.a symbols in libbar.so, then the fact that libfoo.so was also linked with ipps.a should become irrelevant.



Related Topics



Leave a reply



Submit