为什么gcc在x86_64上编译静态库时不隐式提供-fPIC标志
我在编译静态链接到静态库的共享对象时遇到了很多问题。此问题仅在x84_64平台上出现。在x86_32上执行相同的编译工作时,我没有任何问题 也许这是一种特定于操作系统的GCC配置,但我的研究表明,这是GCC在x86_64平台上的工作方式。无论如何,我在Ubuntu 10.04 x86_64上使用GCC4.4.3 问题是如何解决的?。。。确保使用-fPIC编译所有静态库依赖项 问题1:-fpic和-fpic之间有什么区别(显然-fpic在x86上生成更多指令)?为什么后面的类型在x86_64上下文中更相关 问题2:我的假设是,当你链接静态代码时,你是在链接时将函数硬连接到二进制文件中,为什么它需要“位置独立代码”机制提供的间接级别 问题3:现在,如果x86不需要-fpic/-fpic将共享对象链接到静态归档文件,为什么x86\u 64中需要它 问题4:即使需要,为什么不隐式提供?我认为打破改变应该是一个很大的禁忌为什么gcc在x86_64上编译静态库时不隐式提供-fPIC标志,gcc,compilation,dynamic-linking,static-linking,gnu-toolchain,Gcc,Compilation,Dynamic Linking,Static Linking,Gnu Toolchain,我在编译静态链接到静态库的共享对象时遇到了很多问题。此问题仅在x84_64平台上出现。在x86_32上执行相同的编译工作时,我没有任何问题 也许这是一种特定于操作系统的GCC配置,但我的研究表明,这是GCC在x86_64平台上的工作方式。无论如何,我在Ubuntu 10.04 x86_64上使用GCC4.4.3 问题是如何解决的?。。。确保使用-fPIC编译所有静态库依赖项 问题1:-fpic和-fpic之间有什么区别(显然-fpic在x86上生成更多指令)?为什么后面的类型在x86_64上下文
此外,我的建议是:如果你需要担心这一点,那就是你做错了(或者你喜欢用艰苦的方式学习,这很好,因为你会从经验中获得更多)。编译系统(libtool、cmake,无论您使用什么)都应该为您做到这一点。典型的
。
静态库只是常规.o
对象的集合
因此,从概念上讲,您通常可以使用命令行上完全相同的.o
文件列表替换.a
,这些文件不需要重新定位
例如,考虑以下情况:
a、 c
a、 h
b、 c
b、 h
main.c
#include <assert.h>
#include <stdlib.h>
#include "a.h"
#include "b.h"
int main(void) {
assert(a() == 1);
assert(b() == 2);
return EXIT_SUCCESS;
}
从中我们清楚地看到,ar
只是将a.o
和b.o
打包到ab.a
因此,以下命令也起作用:
gcc -ggdb3 -std=c89 -Wall -Wextra -pedantic-errors main.o a.o b.o -o maina.out
从这一点可以清楚地看出,一般来说,归档文件中的对象文件不需要与位置无关
如果您希望,例如将它们链接到共享库中,您可以使其位置独立。一切都像以前一样适用:.a
只包含它们而不修改它们
这个答案可能也很有趣:
在Ubuntu 20.04上测试。关于问题1。-fpic和-fpic之间的区别在“如何编写共享库”中描述。寻找“两个选项中的哪一个,-fpic或-fpic必须使用”。我以前浏览过那篇文章的部分内容,我希望我可以不必提取答案(问题也有两部分,这一部分是否涵盖了这两部分?):我接受了你的答案:D我还没有机会查看你的信息。但我会调查一下,稍后会对你的回答发表评论。谢谢。第2点:当将共享代码链接到静态库时,为什么共享代码要求使用-fPIC编译静态库?我不明白,难道它不能在编译时链接过程中添加任何丢失的地址信息吗?当你将一个静态库链接到一个共享库中时,它不再涉及目标代码,所以它首先需要以正确的方式编译(使用PIC)。我面临的问题是依赖性,我自己使用cmake。Boost/protobuf和openssl都不为x86_64静态库提供fPIC。考虑到CMake,您可以在他们的用户邮件列表或此处询问。通过谷歌搜索,我发现了相关问题的讨论,所以这可能不是他们列表上的一个离题话题。
#include "b.h"
int b(void) { return 2; }
#ifndef B_H
#define B_H
int b(void);
#endif
#include <assert.h>
#include <stdlib.h>
#include "a.h"
#include "b.h"
int main(void) {
assert(a() == 1);
assert(b() == 2);
return EXIT_SUCCESS;
}
gcc -ggdb3 -std=c89 -Wall -Wextra -pedantic-errors -fPIC -c 'main.c' -o 'main.o'
gcc -ggdb3 -std=c89 -Wall -Wextra -pedantic-errors -fPIC -c 'a.c' -o 'a.o'
gcc -ggdb3 -std=c89 -Wall -Wextra -pedantic-errors -fPIC -c 'b.c' -o 'b.o'
ar rcs ab.a a.o b.o
gcc -ggdb3 -std=c89 -Wall -Wextra -pedantic-errors main.o ab.a -o maina.out
./maina.out
gcc -ggdb3 -std=c89 -Wall -Wextra -pedantic-errors main.o a.o b.o -o maina.out