I've got a static library, a dynamic library (which uses the static), and an executable (that uses both):
$ cat static.cpp
int use_static()
{
return {};
}
void unused_in_static() {}
$ cat shared.cpp
void use_static();
void use_shared()
{
use_static();
}
void unused_in_shared() {}
$ cat app.cpp
void use_shared();
void use_static();
int main()
{
use_shared();
use_static();
}
Then I build them:
#!/bin/bash -xe
COMPILE_OPTIONS="-ffunction-sections -fPIC"
g++ $COMPILE_OPTIONS -c -o static.o static.cpp
ar qc libstatic.a static.o
g++ $COMPILE_OPTIONS -c -o shared.o shared.cpp
g++ -Wl,-gc-sections -shared -o libshared.so shared.o libstatic.a
g++ $COMPILE_OPTIONS -c -o app.o app.cpp
g++ -Wl,-gc-sections -Wl,-rpath=. -o app app.o libstatic.a libshared.so
The strange thing is, that the compiled app contains the function unused_in_static which is not used anywhere:
readelf -s app | grep unused
13: 000000000000079a 7 FUNC GLOBAL DEFAULT 14 _Z16unused_in_staticv
57: 000000000000079a 7 FUNC GLOBAL DEFAULT 14 _Z16unused_in_staticv
I would expect that it will be removed (thanks to -ffunction-sections and -Wl,-gc-sections).
The same happens if I add the libstatic to the linker after libshared:
g++ -Wl,-gc-sections -Wl,-rpath=. -o app app.o libstatic.a libshared.so libstatic.a
But, surprisingly, if I reverse the order of libshared and libstatic, everything works ok:
g++ -Wl,-gc-sections -Wl,-rpath=. -o app app.o libshared.so libstatic.a
readelf -s app | grep unused
Why garbage collecting of the unused function depends on link order? Isn't the first or the second linking order correct?