将静态库链接到不带-fPIC的共享库中
Linking a static library into a shared library without -fPIC
我想将对象文件和静态库组合成一个共享库,但静态库不应公开,它只在进入共享库的对象文件中引用。我认为在这种情况下,我不需要用-fPIC
编译静态库,但我不知道如何告诉链接器我不会使用静态库中的符号。为了说明我的问题,请使用以下文件:
文件foo.cpp
:
#include "static.h"
using namespace std;
string version_info()
{
return static_version_info();
}
文件static.cpp
:
#include"static.h"
#include <vector>
using namespace std;
string static_version_info()
{
std::vector<int> ivec;
return to_string(ivec.size());
}
文件static.h
:
#ifndef STATIC_H
#define STATIC_H
#include<iostream>
using namespace std;
std::string static_version_info();
#endif
然后进行
$ g++ -c foo.cpp -o foo.o -fPIC
$ g++ -c static.cpp -o static.o
$ gcc-ar rcs static.a static.o
$ g++ -shared foo.o static.a
/usr/bin/ld: static.a(static.o): relocation R_X86_64_PC32 against symbol `_ZNSt6vectorIiSaIiEEC1Ev' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Bad value
collect2: error: ld returned 1 exit status
问题:我如何调整最后一个命令,这样我就不会出错?这可能吗?
请注意,我不想用-fPIC
编译static.cpp
,并且我不需要共享库中的符号(此处为return_static_version_info()
(
您不能(或者至少不应该(将静态库链接到共享库。
即使你碰巧成功地将非PIC静态库libX.a
链接到共享库libY.so
,结果也不会有与位置无关的代码(因此会有很多"无用"或"烦人"的重新定位(。
共享库只需要包含与位置无关的代码(在实践中(;但是静态库不包含PIC。
我不想用-fPIC 编译static.cpp
但你真的应该这样做。
有关详细信息,请阅读Drepper的如何编写共享库。
顺便说一句,一些Linux发行版(例如Debian(提供了一个libc6-pic
包,该包提供了/usr/lib/x86_64-linux-gnu/libc_pic.a
等文件,这些文件是位置无关代码的静态库。这可能用于扩展系统的libc.so.6
,例如您自己的功能(或您自己的malloc
等(
在实践中,您将更好地使用-fPIC
重新编译静态库代码;顺便说一句,x86-64 ISA是为了方便PIC而设计的。
最后,如果您关心优化,那么它们有很多。您是否考虑过用gcc -O3 -fPIC -flto
编译并链接?在某些情况下,您可能会考虑-ffast-math
(它可以针对C标准进行优化(,或者用-Ofast
替换-O3
。
当然,您应该使用最新的GCC或Clang编译器(或最新的专有icc
(。这个老问题(在你的评论中提到(大约是4.7。目前2018年秋季的GCC是GCC 8,GCC 9正在制定中(因此应在2019年春季出现(。目前的Clang是Clang 7。编译器在优化方面不断取得进展。
您可能想下载GCC或Clang最新版本的源代码tarball,并在您的计算机上构建它。这是拥有这些编译器的最新版本的好方法,因为发行商通常更喜欢它们的旧版本(即使与非标准兼容代码也兼容(。
- 将成员变量添加到共享库中的类中,不会破坏二进制兼容性吗
- 是否可以通过C++扩展强制多个python进程共享同一内存
- 在cuda线程之间共享大量常量数据
- 如何从具有移动语义的类对象中生成共享指针
- 在c代码之间共享数据的最佳方式
- 在两个类中共享相同的函数调用,并在不需要时避免空实例化
- 将静态库链接到不带-fPIC的共享库中
- 为什么std::互斥需要很长的、非常不规则的时间来共享
- 使用Boost Interprocess创建托管共享内存需要很长时间
- 无法在Ubuntu上将共享库与Eclipse链接
- 从python调用openMP共享库时,未定义opnMP函数
- 在为LINUX创建共享库时,如何避免STL的私有/弱副本
- 为什么我的共享库中存在展开符号
- 使用共享指针的函数调用,其对象应为 const
- 具有两个独占锁组的共享锁
- 共享队列的线程安全
- 除了共享库之外,g++ -fPIC 也适用于可执行文件
- 在创建共享对象时,不能使用针对未定义符号的重定位R_X86_64_PC32;使用-fPIC重新编译
- Linux上的共享库和-fPIC错误
- 将静态 (.a) 库与共享 (.so) 库链接,得到错误"relocation R_X86_64_32S against a local symbol; recompile with -fPIC"