Issue
Consider the following source files:
a.c:
extern int baz();
int foo() { return 123; }
int bar() { return baz() + 1; }
b.c:
extern int foo();
int main() { return foo(); }
Now, when I try to build a program using these sources, here's what happens:
$ gcc -c -o a.o a.c
$ gcc -c -o b.o b.c
$ gcc -o prog a.o b.o
/usr/bin/ld: a.o: in function `bar':
a.c:(.text+0x15): undefined reference to `baz'
collect2: error: ld returned 1 exit status
This is on Devuan GNU/Linux Chimaera, with GNU ld 2.35.2, GCC 10.2.1.
Why does this happen? I mean, one does not need any complex optimization to know that baz()
is not really needed in foo()
- ld naturally notices this at some point - e.g. when finishing its traversal of foo()
without noticing a location where baz()
is used.
Now, you could say "einpoklum, you didn't ask the compiler to go to any trouble for you" - and that's fair, I guess, but even if I use -O3
with these instructions, I get the same error.
Note: with LTO and optimization enabled, we can circumvent this issue:
$ gcc -c -flto -O1 -o b.o b.c
$ gcc -c -flto -O1 -o a.o a.c
$ gcc -o prog -O1 -flto a.o b.o
$ /prog ; echo $?;
123
Solution
If you use gcc
and binutils ld
to build your programs you need to place functions in separate sections. It is archived by -fdata-sections
& -ffunction-sections
command line options.
Same with data. Then if you do not want dead code to be included in your executable you need to enable it by using --gc-sections
ld
option.
Putting this all together:
$ gcc -fdata-sections -ffunction-sections -c -o a.o a.c
$ gcc -c -o b.o b.c
$ gcc -Wl,--gc-sections -o prog a.o b.o
$ /prog ; echo $?
123
If you want to enable it by default simple build GCC
with those options enabled.
Answered By - 0___________ Answer Checked By - Marie Seifert (WPSolving Admin)