Does the gcc's option -static affect only one library that follows immediately or does it affect all libraries provided on command line?
g++ -static -lutils1 -lutils2
GGC's -static linkage option prevents linkage with shared libraries. So
all libraries that the linkage requires must be static. The
linker must be able to find a static library to resolve all -lname options that
are passed, as well as static versions of all default libraries that GCC silently
appends to the linkage.
That is the intended use of the -static option, although it is possible to make it more flexible.
GCC's -static option works simply by causing GCC to pass the option -static|-Bstatic to the linker (ld), at
a position in the generated ld commandline that precedes all the libraries in
the linkage.
The linker's -static option has a different meaning from GCC's. From the ld manual:
-Bstatic
-dn
-non_shared
-static
Do not link against shared libraries. This is only meaningful on platforms for which shared libraries are supported.
he different variants of this option are for compatibility with various systems.
You may use this option multiple times on the command line: it affects library searching for -l options which follow it.
(My emphasis)
So the linker's -static|-Bstatic option means: Do not link any shared libraries until further notice. At a later
point in the ld commandline you may cancel the effect of -static|-BStatic with the option -Bdynamic, which
will allow dynamic libraries to be linked again, from that point on, until further notice.
Unlike the linker, GCC has no option that cancels the effect of its -static option. However, GCC allows you to pass abitrary options through to ld, via -Wl,<ld-options>.
So you can in fact cancel GCC's -static option at a later point in the commandline like this:
gcc -static -o prog main.o -lfoo -lbar -Wl,-Bdynamic -lgum ...
This will generate a linkage commandline in which -lfoo and -lbar must be resolved to
static libraries but -lgum and any subsequent library can be resolved to
a shared library or a static library, as usual. Though if you wanted to "turn on/turn off"
dynamic linkage like this at different points in the commandline, it would be more
natural not to use GCC's -static option and instead write the equivalent:
gcc -o prog main.o -Wl,-Bstatic -lfoo -lbar -Wl,-Bdynamic -lgum ...
Related
This question already has answers here:
Use both static and dynamically linked libraries in gcc
(3 answers)
Closed 5 years ago.
First of all I would like to give some background information to avoid the XY Problem.
I am trying to compile a c++ program using makefiles and g++. I also have to build any dependencies statically into the program, but not the 'system libraries' (libz.so, libdl.so, libstdc++.so, libm.so, libpthread.so, libc.so and libgcc.so).
To achieve this I specify -static as linker flag, then all dependencies that have to be statically linked and then I use the -Wl, -Bdynamic option, that should tell the linker to link every library, after this option, to be linked in dynamically including the 'system libraries' because they get linked last.(please correct me if I am wrong.)
LDFLAGS += -Lpath/to/dependencies
# These libs should be linked statically
LDFLAGS += -static
LDFLAGS += -llib1
LDFLAGS += -llib2
LDFLAGS += -llib3
# Libs after this should be linked dynamically.
LDFLAGS += -Wl, -Bdynamic
LDFLAGS += -lz # If i dont specify these three libraries (z, pthread, dl)
LDFLAGS += -lpthread # I get undefined reference errors
LDFLAGS += -ldl
When I call make, the program compiles and links just fine, but when I try to execute it I get the error: bash: ./program: No such file or directory.
But the file DOES exist.
When I remove the -static flag from the linker, the program can be excecuted just fine, but the dependencies are linked dynamically, which is not what I want :(.
So when I call file on the program, that was made with the -static flag, I get this:
program: ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), dynamically linked, interpreter /usr/lib/libc.so.1, for GNU/Linux 4.9.0, not stripped
The problem seems to be that the interpreter is set to /usr/lib/libc.so.1 and not to /lib/ld-linux.so.2 as it should usually be. At least it is, when I compile without the -static option.
What I found out is that the 'interpreter' is in reality the shared library loader and from what I read, I now assume that the bash tells me it can not find the program because the library loader is just wrong (Even though I don't quite understand the details of this).
So basically my question is: Why does the library loader get set to libc.so when I specify the -static option to the linker and how can I tell the linker to use the correct library loader when -static is specified?
Your error is mixing -static and -Bdynamic as both compiler and linker flags. Don't do that. If you use -Wl, gcc just blindly pass these flags to the linker, but if you don't, it rearranges the entire link line. (check what it does with gcc -v).
The mix creates an inconsistent and erroneous link command. I have no idea why gcc doesn't at least warn about that, but it doesn't, and silently sets the dynamic loader to a non-existent file.
You want to use -Wl,-Bstatic and -Wl,-Bdynamic consistently throughout. Not -Bstatic and -Bdynamic, as gcc logic is different from that of ld.
This will create a correct dynamically linked executable with some static libs linked in.
I am developing and testing some code on 2 different machines: my own *buntu laptop and a remote linux machine configured by someone else.
My code uses a library, let's say libfoo, that in turn depends on, say, libbase.
I would like to keep a single makefile across both the machines, but I found out things works differently when I build my project (with GCC):
On my laptop, I need to specify -lfoo -lbase for the code to link
correctly.
On the remote machine, I only need the -lfoo flag, and the linker
somehow picks up the base library automagically.
Anyone knows what is going on? Is there any flag that might have been passed when building libfoo from source that made this automatical "depencency detection" possible?
PS: I know I could just specify every library in the make file, but keeping the list of flags to the minimum looks interesting, and I would like to know what's going on under the hood.
Yes. Both -lfoo and -lbase refer to some shared libraries libfoo.so and libbase.so (perhaps with some version number).
On the remote machine, libfoo.so was built and linked to libbase.so, perhaps from some foo1.c and foo2.c like
gcc -Wall -O -fPIC foo1.c -o foo1.pic.o
gcc -Wall -O -fPIC foo2.c -o foo2.pic.o
gcc -shared -O foo1.pic.o foo2.pic.o -lbase -o libfoo.so
(of course, probably some Makefile did run above commands thru make)
On your own laptop, you (or your distribution maker) did not link -lbase inside libfoo.so
Read Drepper's how to write shared library (long) paper (and the program library howto)
It is possible to link a shared (low-level) library inside another (higher-level) shared library (and that is not possible with static libraries libfoo.a).
You could use ldd on (the absolute path of) your libraries libfoo.so and libbase.so to find out how they have been linked.
How can I get GCC to use that static library instead of the dynamic one? Normally you add the .a file to the linker parameters. But libssp linking is triggered by the -fstack-protector option. And compiler prefers linking to the shared library if it finds one instead of static library.
If I try to run the resulting program on systems that don't have the libssp.so the program won't run.
(After system upgrade on some build machines, the older boxes on the test system screwed up)
Does
gcc -static static.c -o static -fstack-protector-all
or
gcc -static -lssp static.c -o static -fstack-protector-all
work? Can you run ldd on the resulting binaries?
What version of gcc are you using?
I have a problem building a shared library with GCC/Linux. Currently this shared library is created with GCC/libtool option "-shared" and everything is fine.
Now there are two additional, static libraries (.a-files) that have to be added to this shared one since they provide some functionality that is required by the shared one. Adding these static libraries with option "-l" does not help, afterwards they are not part of the .so file.
So how can I force GCC/libtool to really add the code of these static libraries to the shared library?
Thanks!
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.
You only need the --whole-archive parameter to force the linker to include the library, but it should be able to infer its own needs from unmatched symbols.
Ensure that any static libraries on the command-line come after their dependent object-files e.g.:
g++ -Wl,-E -g -pipe -O2 -pipe -fPIC myobjectfile.o mystaticlibrary.a -shared -o mylib.so
I am working in Linux, Eclipse CDT, g++, with Boost library. Having existing program which uses Boost thread, I try to link it statically instead of dynamically. /usr/local/lib directory contains the following files:
libbost_thread.a
libbost_thread.so
libbost_thread.1.41.0
Dynamic linking works:
g++ -o"MyProgram" ./main.o -lboost_thread
Static linking:
g++ -static -o"MyProgram" ./main.o -lboost_thread
produces huge number of messages like:
undefined reference to `pthread_mutex_init'
How can I link statically to the Boost library?
For pthread_mutex_init, you want to compile/link with -pthread option:
g++ -static -pthread -o"MyProgram" ./main.o -lboost_thread
The problem is that functions like pthread_mutex_init are in a separate library. Dynamic libraries can include the metadata for the fact that it needs the separate library (so libboost_thread.so includes the fact that it needs libpthread).
But static libraries don't have that information. So you need to provide the reference to any necessary libraries when you link statically.
As for using -pthread instead of -lpthread, it's slightly preferable because it not only links the necessary library, but provides any other options that should be used (such a -D_REENTRANT to the compiler).
Try adding -lpthread to your invocation.
On Linux a dynamic library may automatically depend on other dynamic libraries so that when you link it, you get the other libraries for free. When linking statically, there is no such system and you have to specify the other libraries manually.