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
Svn Checkout the Contents of a Folder, Not the Folder Itself
How to Find Out Why My Storage Space on Amazon Ec2 Is Full
Append Text to File from Command Line Without Using Io Redirection
How to Change Permissions to Certain File Pattern/Extension
How to Get the Exit Code of Spawned Process in Expect Shell Script
Linux Command to Translate Domain Name to Ip
How to Extract Filename.Tar.Gz File
How to Request a File But Not Save It with Wget
Replace Only If String Exists in Current Line
Logo Programming Language Implementations
Delete Files with String Found in File - Linux Cli
Does Os X Have an Equivalent to /Dev/Shm
Matlab Execute Script from Linux Command Line
Bash "Declare -A" Does Not Work on MACos
How to Mount One Partition from an Image File That Contains Multiple Partitions on Linux