For the reference I'm using MinGW (GCC 5.3). When compiling a file with
g++ file.cc -static-libstdc++
it statically links the C++ standard lib (libstdc++
) and produces a 1.9MB executable.
However running
gcc -lstdc++ -static-libstdc++ file.cc
it still dynamically links to libstdc++-6.dll
and produces a 34KB executable.
Why does -static-libstdc++
only work with g++
but not with pure gcc
?
The __attribute__ directive is used to decorate a code declaration in C, C++ and Objective-C programming languages. This gives the declared code additional attributes that would help the compiler incorporate optimizations or elicit useful warnings to the consumer of that code.
GCC has a range of optimization levels, plus individual options to enable or disable particular optimizations. The overall compiler optimization level is controlled by the command line option -On, where n is the required optimization level, as follows: -O0 . (default).
Optimization level -O3 -O3 instructs the compiler to optimize for the performance of generated code and disregard the size of the generated code, which might result in an increased code size. It also degrades the debug experience compared to -O2 .
Turning on optimization flags makes the compiler attempt to improve the performance and/or code size at the expense of compilation time and possibly the ability to debug the program. The compiler performs optimization based on the knowledge it has of the program.
The GCC manual, Link Options says:
-static-libstdc++
When the g++ program is used to link a C++ program, it normally automatically links against libstdc++. If libstdc++ is available as a shared library, and the -static option is not used, then this links against the shared version of libstdc++. That is normally fine. However, it is sometimes useful to freeze the version of libstdc++ used by the program without going all the way to a fully static link. The -static-libstdc++ option directs the g++ driver to link libstdc++ statically, without necessarily linking other libraries statically.
This makes clear that the option -static-libstdc++
is meaningful only to
the g++
compiler driver, not gcc
or any other.
On the other hand the option -l<name>
is meaningful and means the same thing
to all GCC compiler drivers. On that basis it is not surprising that:
gcc file.cc -lstdc++ -static-libstdc++
has the same meaning as:
gcc file.cc -lstdc++
However, that observation does not truly illuminate why the first of those
commandlines dynamically links libstdc++
:-
-static-libstdc++
is meaningful only to g++
because only g++
links
libstdc++
automatically. So it is only for g++
that the question arises
whether the automatically linked libstdc++
will be the dynamic version
or the static version. The dynamic version is the default: -static-libstdc++
insists on the static version.
The automatic linking of libstdc++
by g++
means this: g++
silently
appends -lstdc++
to whatever linkage options you specify (along with
quite a lot of other boiler-plate for a C++ linkage). You can reveal all
the boilerplate by requesting verbose linkage (g++ ... -Wl,-v ...
).
By itself, the appended -lstdc++
will cause the linker to link the dynamic version
of libstdc++
, per its default behaviour. The only difference made by
-static-libstdc++
is that in the place where -lstdc++
would otherwise
be silently passed to the linker, the options:
-Bstatic -lstdc++ -Bdynamic
are silently passed to it instead. These tell the linker:
-Bstatic
: Do not link dynamic libraries until further notice-lstdc++
: Link libstdc++
-Bdynamic
: Link dynamic libraries until further notice.You see how that works to secure the static linkage of libstdc++
without
out side-effects on the linkage of any other library.
But you can also see that the automatic linkage of libstdc++
, whether
dynamically or statically, has no retroactive effect on the linkage
of any libraries you have specified yourself.
Hence, if your linkage already includes -lstdc++
before any boiler-plate
options are silently appended by the compiler driver, then libstdc++
will be linked
in just the same way as any -l<name>
at that position in the linkage
sequence. And if silently appended boiler-plate options result in -lstdc++
reappearing later in the linkage sequence, whether by itself or with
the surroundings:
-Bstatic -lstdc++ -Bdynamic
then the later appearance will simply be redundant, because the library has already been linked.
So there is nothing peculiar about gcc
that results in:
gcc file.cc -lstdc++ -static-libstdc++
producing a program in which libstdc++
is dynamically linked. So does
g++ file.cc -lstdc++ -static-libstdc++
or indeed:
g++ file.cc -static-libstdc++ -lstdc++
because the generated linker commandline is of the form:
... file.o -lstdc++ ... -Bstatic -lstdc++ -Bdynamic ...
where -Bstatic -lstdc++ -Bdynamic
is too late to make any difference.
Check it out:
file.cc
#include <iostream>
int main()
{
std::cout << "Hello World" << std::endl;
return 0;
}
Compile and link normally and inspect the dynamic dependencies with ldd
:
$ g++ -o prog file.cc
$ ldd prog
linux-vdso.so.1 => (0x00007ffede76a000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f42fa74c000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f42fa385000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f42fa07c000)
/lib64/ld-linux-x86-64.so.2 (0x0000558ab42bc000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f42f9e65000)
libstdc++.so
is present.
Now just with -static-libstdc++
:
$ g++ -o prog file.cc -static-libstdc++
$ ldd prog
linux-vdso.so.1 => (0x00007fff448d7000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fe5f7c71000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fe5f78aa000)
/lib64/ld-linux-x86-64.so.2 (0x0000556ebf272000)
libstdc++.so
is absent.
And finally with -static-libstdc++ -lstdc++
:
$ g++ -o prog file.cc -static-libstdc++ -lstdc++
$ ldd prog
linux-vdso.so.1 => (0x00007ffd12de9000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fd5a1823000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd5a145c000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fd5a1153000)
/lib64/ld-linux-x86-64.so.2 (0x000055bbe31c3000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fd5a0f3c000)
libstdc++.so
is back.
(This is Linux, of course, but you'll find the same thing on Windows).
So whether you drive your linkage with g++
or gcc
, the reason that
{gcc|g++} file.cc -lstdc++ ...
will result in libstdc++
being dynamically linked is simply that
{gcc|g++} file.cc -lfoo ...
will cause libfoo
to be dynamically linked, if it can be, regardless of
what ...
is, provided only that ...
does not contain the option -static
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With