Originally posted by: pwaehnert
In the meantime I created a further minimal example based on our framework and got the following, as i think, crucial insight: The AIX linker prefers to resolve weak definitions from the first object file and static library from the command line.
Given the situation I have two static libraries libuseless.a and libhelper.a. The library libuseless.a contains an object file defining a normal symbol useless_func and a weak symbol weak_symbol. The library libhelper.a contains an object file defining another normal symbol helper_func and the same weak symbol weak_symbol.
Now if we want to use the symbol helper_func of libhelper.a in a binary, we have to link against libhelper.a. The linker pulls in the object file from libhelper.a containing helper_func in order to resolve this symbol. But this object file also contains weak_symbol. The linker now seems to reflect about all locations where he previously saw weak_symbol in order to decide which one he really wants to use. If the linker call contains libuseless.a before libhelper.a, the linker prefers the weak symbol weak_symbol from libuseless.a. But since this weak symbol is defined inside an object file also containing the symbol useless_func, the final binary ends up containing this useless symbol too. If this useless symbol depends on a large tree of further symbols, the resulting binary may contain large portions of dead and useless code. In our case, the final libraries contained 20 MB of dead code on the average.
On the other hand, if the linker call lists libuseless.a after libhelper.a, the linker prefers weak_symbol from libhelper.a and thus discards all object files from libuseless.a. The final binary does not contain the symbol useless_func.
This behavior is different from the linkers on Windows, macOS and GNU/Linux. Those linkers discard the object files from libuseless.a nonetheless and prefer the weak symbols from object files which are already included.
I can circumvent this behavior of the AIX linker by using the linker flag -bweaklocal, as you already recommended.
Summary: I had to use both flags you already mentioned together in order to reduce the final binary sizes to something somewhat acceptable:
-
-qtwolink prevents the inclusion of static globals from unused object files from static libraries
-
-bweaklocal prevents the inclusion of weak symbols and neighbor symbols from otherwise completely unneeded object files from static libraries
Those two flags reduced the overall size of our framework by nearly 1.8 gigabytes. Thank you!
#C/C++andFortran#Ask-Question-Here--General-Compiler-Q-and-A