环境:Ubuntu 16.04
在我的实验中,我运行了以下命令:
gcc -c 1.c
gcc -c -fPIC 2.c
gcc -shared 1.o 2.o -o libmyxxx.so
我需要公开的函数都是通过
extern "C"
声明在 2.c 中定义的。这些函数在内部调用 1.c. 中定义的其他函数
请注意,我没有将
-fPIC
应用于 1.c。尽管如此,一切似乎都可以正常编译/链接,没有任何警告。
我们是否可以得出结论,
-fPIC
必须仅应用于那些公开外部函数的源文件?
在更大的图片中,我有一堆存档(.a)文件,这些文件可能没有使用
-fPIC
标志进行编译。我需要创建一个与这些存档文件链接的自定义共享库。如果我的假设是有效的,我认为链接这些存档文件就可以了。欣赏你的想法。问候。
我们是否可以得出结论:-fPIC 必须仅应用于那些源文件 暴露外部函数?
不,我们不能。
-fPIC
的唯一目的是确保生成的机器代码可以链接到位置无关的二进制文件。尽管如此,即使源代码是在没有 -fPIC
的情况下编译的,某些代码也可能看起来是 PIC 就绪的。它可能是没有外部依赖的简短的自包含函数,无论生成的目标文件中不需要辅助数据结构,如 PLT 和 GOT 条目。
无论如何,如果您的目标文件无法链接到位置无关的二进制文件,链接器将失败并显示全面的错误消息。并且您需要使用这个神奇的选项重新编译它。
因此,您应该始终将
-fPIC
放到共享库的 CFLAGS
中,以节省您自己的时间并避免浪费的重新编译。
如果可执行文件中有一个目标文件,并且在没有 -fPIC 标志的情况下进行编译,则将存在具有“位置相关内存引用”的程序文本页面。这些页面将无法在运行时重新定位到合适的虚拟内存地址(这主要是共享对象的目的)。当您在其他机器上构建代码或将 .so 链接到其他代码时,这些依赖于位置的内存引用会来咬你。 -fPIC 需要生成与位置无关的代码:
全局变量