There are 3 files a.c, b.c, main.c:
// a.c
int a() { return 123; }
// b.c
extern int a();
int b() { return a(); }
// main.c
#include <stdio.h>
extern int b();
int main() {
printf("%d\n", b());
return 0;
}
a.c is build as a static library liba.a.
b.c is build as a shared library libb.so.
liba.a is then linked with (i.e. included into) libb.so.
main.c is built as an executable, and dynamically linked to libb.so.
The Makefile looks like:
all:
gcc -c -fPIC -o a.o a.c
ar rcs liba.a a.o
gcc -c -fPIC -o b.o b.c
gcc -shared -o libb.so b.o liba.a
gcc -o main -L. -lb
b.o is compiled with the position-independent code flag, because it becomes a shared library.
Is it necessary to also build a.o as position-independent code, because it will be included into a shared library? At least on the system I'm testing it on, it seems to work fine when the first -fPIC is removed.
Also, if main.c would be changed to also declare extern int a() and call it (assuming libb.so makes it visible), would it then be needed to compile a.o as position-independent code? (On my system this also works without the -fPIC for a.o).
Yes, all code that goes into shared library has to be compiled with
-fPICregardless of whether it's in an object file or static library.It works without
-fPICin your case because modern distros enable-fPICby default for security reasons:It's better to keep it explicit in your build scripts for clarity though.