Linux 中使用 g++ 进行静态编译

4

我已经静态编译了OpenSSL库。我希望能够将OpenSSL库与MyModule一起静态编译。我使用Makefile来完成同样的操作。

LDFLAGS      = $(LD_SHARED_FLAGS) -fPIC -static -lssl -lcrypto

在根目录的 Makefile 中,LD_SHARED_FLAGS 的设置是与共享库相关的。
LD_SHARED_FLAGS     = -z text

当我运行make命令时,出现以下错误:
g++ -shared -L../../lib  -z text -fPIC -static -lssl -lcrypto  -o libMyModule.so debug_utils.o  MyModule.o   labels.o -L/path_to_openssl/lib -lssl -lcrypto -lc

/usr/bin/ld: /usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtbeginT.o: relocation R_X86_64_32 against `__TMC_END__' can not be used when making a shared object; recompile with -fPIC

/usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtbeginT.o: error adding symbols: Bad value

collect2: error: ld returned 1 exit status

make: *** [libMyModule.so] Error 1

我是否使用了正确的标志进行静态编译?

如何解决这个错误?


2
我认为你的意思是“链接”,而不是“编译”。 - Barmar
你是否注意到错误信息中的建议,即“使用-fPIC重新编译” - Toby Speight
2个回答

7

看起来您想将静态库 libssl.alibcrypto.a 链接到共享库 libMyModule.so 中。

在链接命令中添加 GCC 选项 -static 并不只有这个效果,而是一个更大的影响。它的作用是要求进行完全静态链接。链接器必须找到并使用所有所需库的静态版本:不仅是您在链接命令中指定的库,还包括默认的库:libclibstdc++libgcc,以及 C 运行时支持二进制文件的静态链接变量,crt*.o

可能,您并不想要所有这些-static东西,即使您不介意它,它也与 -shared 不兼容。

当然,您需要 -shared 来制作共享库。被链接到共享库中的所有目标文件都必须是位置无关代码,并使用 -fPIC 编译。

您遇到的错误:

/usr/bin/ld: /usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtbeginT.o: \
relocation R_X86_64_32 against `__TMC_END__' can not be used when making a shared object; \
recompile with -fPIC

告诉您,链接所需的C运行时二进制文件没有使用<-fPIC>编译;不是位置无关代码,因此无法链接到共享库中。
但是,是由<-static>选项要求进行链接的。如果您没有指定<-static>,则将链接,这是用于与共享库链接的该运行时二进制文件的PIC变体,因此不会出现错误。
因此,请勿指定<-static>。它与<-shared>不兼容,并且不是将和的静态版本链接到的方法。
有多种方法可以实现这一点。最简单的方法是将您的链接命令中的<-lssl -lcrypto>替换为明确指定这些库的静态版本的选项,即:
-l:libssl.a -l:libcrypto.a

哇,那可能是我遇到过的最好的答案。非常感谢! - Error404

1
重新使用-fPIC选项构建openssl静态库。

我不知道R_X86_64_32是什么,但它表明您已经构建并链接了32位二进制文件。如果您在openssl库上执行file ...命令,它会显示32位还是64位?(X86_64是CPU架构,而不是二进制位数)。 - Mischa
文件 libcrypto.a libcrypto.a:当前的 ar 存档 - Supriya Surendra

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接