<div dir="ltr">I've researched the linking process and here is what I've found.<br><br>First of all, let's talk about symbols removal. Here is an interesting note on<br>how it works: <a href="https://stackoverflow.com/questions/55130965/when-and-why-would-the-c-linker-exclude-unused-symbols">https://stackoverflow.com/questions/55130965/when-and-why-would-the-c-linker-exclude-unused-symbols</a><br>One of the basic important concepts is an ELF section. It's a chunk of data<br>(assembly code in our case) that linker operates on. A section may contain code<br>of one or more functions (depending on build arguments), but it can't be split<br>during linking.<br><br>Usually, when we build an object file with `gcc libx.c -c -o libx.o`, all<br>functions from libx.c go into the single ".text" section. This single object<br>file is usually archived with others into single libx.a, which is later<br>processed during main executable linking.<br><br>By default (but I can't provide the proof), when we call `gcc -lx` linker<br>operates on object files from the archive - if at least one symbol is used,<br>whole .o (not .a) is included in the resulting binary. There are also two linker<br>options that influence this behavior. At first, there is `-Wl,--whole-archive`,<br>which makes it to include whole `.a` instead of `.o` granularity. Secondly, there is<br>`-Wl,--gc-sections` which could remove unused sections, but in basic example<br>it's useless since all symbols from .o belong to the same .text section. To make<br>`--gc-sections` have an effect one should compile object files with<br>`-ffunction-sections` flag. It'll generate a separate section for every function<br>so the linker could gc unused ones.<br><br>See:<br>```console$ cat libx.c <br>#include <stdio.h><br><br>void fA() {<br>        printf("fA is here\n");<br>}<br>void fB() {<br>        printf("fB is here\n");<br>}<br>$ gcc libx.c -c -o libx.o -ffunction-sections<br>$ readelf -S libx.o | grep .text<br>  [ 1] .text             PROGBITS         0000000000000000  00000040<br>  [ 5] .text.fA          PROGBITS         0000000000000000  00000056<br>  [ 6] .rela.text.fA     RELA             0000000000000000  000002d8<br>  [ 7] .text.fB          PROGBITS         0000000000000000  0000006d<br>  [ 8] .rela.text.fB     RELA             0000000000000000  00000308<br>```<br><br>Now let's move to the `libbit` which Vlad mentioned.<br>I've investigated how compiler options influence the resulting binary. Unused<br>functions from bit.c are really remover, but only with Release flags, and here<br>is why:<br><br>There are only 2 functions implemented in bit.c, and both are unused. All the<br>others are inlines in bit.h and externs from luajit. When tarantool is built in<br>debug mode, the inlining is off, so other modules truly link to the bit.o and<br>all symbols remain including unused functions. But if we specify -O2 flag,<br>inlining takes place, and all the symbols from bit.o becomes unused, so the<br>linker drops the whole object file.<br><br>Finally, speaking about this patch, my proposal is to merge this PR as is.<br>And since we know how to manage linking, other problems can be solved separately<br>(if they ever occur).<br><br>Best regards<br>Yaroslav Dynnikov<div><br></div><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, 18 Jun 2020 at 02:09, Vladislav Shpilevoy <<a href="mailto:v.shpilevoy@tarantool.org" target="_blank">v.shpilevoy@tarantool.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On 17/06/2020 17:29, Mavr Huston wrote:<br>
> <br>
> EXPORT_LIST contains following libraries in case of static build (with normal build it's empty):<br>
> <br>
> /usr/lib/x86_64-linux-gnu/libreadline.so<br>
> <br>
> /usr/lib/x86_64-linux-gnu/libcurses.so<br>
> <br>
> /usr/lib/x86_64-linux-gnu/libform.so<br>
> <br>
> /usr/lib/x86_64-linux-gnu/libtinfo.so<br>
> <br>
> /usr/lib/x86_64-linux-gnu/libz.so<br>
> <br>
> /opt/local/lib/libssl.so<br>
> <br>
> /opt/local/lib/libcrypto.so<br>
> <br>
> /usr/lib/x86_64-linux-gnu/libz.so<br>
> <br>
> /opt/local/lib/libicui18n.so<br>
> <br>
> /opt/local/lib/libicuuc.so<br>
> <br>
> /opt/local/lib/libicudata.so<br>
> <br>
> <br>
> It doesn’t contains libcurl because it’s bundled statically. So it isn’t related to <a href="https://github.com/tarantool/tarantool/issues/4559but" rel="noreferrer" target="_blank">https://github.com/tarantool/tarantool/issues/4559but</a> this problem may be solved with next patch: <a href="https://github.com/tarantool/tarantool/tree/rosik/refactor-static-build" rel="noreferrer" target="_blank">https://github.com/tarantool/tarantool/tree/rosik/refactor-static-build</a>. At this patch added flag --disble-symbos-hiding (<a href="https://github.com/tarantool/tarantool/blob/rosik/refactor-static-build/cmake/BuildLibCURL.cmake#L93" rel="noreferrer" target="_blank">https://github.com/tarantool/tarantool/blob/rosik/refactor-static-build/cmake/BuildLibCURL.cmake#L93</a>) at building libcurl and after that most of libcurl symbols are visible from tarantool binary<br>
<br>
The problem is not in the hiding. It is about removal. Not used symbols from<br>
static libs may be removed from the final executable. Hide or not hide rules<br>
are applied to what is left. That is the single reason why we had exports file<br>
before 2971 and have exports.h and exports.c now. You can try it by yourself -<br>
just add an unused function to lib/bit to bit.h and bit.c. And don't use it<br>
anywhere. You may even add 'export' to it, or change visibility rules using<br>
__attribute__ - it does not matter. If the function is not used and is not<br>
added to exports.h, you won't see it in the executable. (At least it was so<br>
last time I tried, works not with all libs, but with lib/bit it worked).<br>
<br>
Seems EXPORT_LIST was used to extract all symbols from the static libs and<br>
force their exposure + forbid their removal. Here the symbols were retrieved:<br>
<a href="https://github.com/tarantool/tarantool/commit/03790ac5510648d1d9648bb2281857a7992d0593#diff-6b9c867c54f1a1b792de45d5262f1dcfL20-L25" rel="noreferrer" target="_blank">https://github.com/tarantool/tarantool/commit/03790ac5510648d1d9648bb2281857a7992d0593#diff-6b9c867c54f1a1b792de45d5262f1dcfL20-L25</a><br>
<br>
Here the libs were passed to mkexports:<br>
<a href="https://github.com/tarantool/tarantool/commit/03790ac5510648d1d9648bb2281857a7992d0593#diff-95e351a3805a1dafa85bf20b81d086e6L253-L260" rel="noreferrer" target="_blank">https://github.com/tarantool/tarantool/commit/03790ac5510648d1d9648bb2281857a7992d0593#diff-95e351a3805a1dafa85bf20b81d086e6L253-L260</a><br>
<br>
We probably should resurrect that part. Rename the current exports.h to <a href="http://exports.h.in" rel="noreferrer" target="_blank">exports.h.in</a><br>
and generate exports.h during cmake. Like it was done for exports before 2971. To<br>
forbid symbols removal. Not to unhide them.<br>
</blockquote></div></div>