【问题标题】:Linking a static library into a shared library without -fPIC在没有 -fPIC 的情况下将静态库链接到共享库
【发布时间】:2018-10-31 15:12:41
【问题描述】:

我想将目标文件和一个静态库合并到一个共享库中,但是静态库不能暴露,它只在进入共享库的目标文件中引用。我认为在这种情况下,我不需要使用-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

问题: 如何调整最后一个命令,以免出现错误?这可能吗?

注意我不想编译 static.cpp with -fPIC 我不需要符号(这里 @987654331 @) 在共享库中。

【问题讨论】:

  • 我没有按照你的思路。如果你...will not use the symbols from the static library...你为什么需要它链接?
  • @SergeyA 静态库仅在与静态库一起链接到共享库的目标文件中定义的接口中使用。我只通过这个接口访问静态库。问题是在这种情况下我是否可以避免 -fPIC 用于静态库。

标签: c++ linker g++ libtool


【解决方案1】:

您不能(或者至少不应该)将静态库链接到共享库

即使您碰巧成功地将非 PIC 静态库 libX.a 链接到共享库 libY.so,生成的东西也不会有与位置无关的代码(因此会有很多“无用的”或“烦人的”搬迁)。

共享库只需要包含与位置无关的代码(在实践中);但静态库不包含 PIC。

我不想用 -fPIC 编译 static.cpp

但你真的应该这样做。

阅读 Drepper 的 How to Write Shared Libraries 了解详情。

顺便说一句,一些 Linux 发行版(例如 Debian)提供了一个 libc6-pic 包,提供了诸如 /usr/lib/x86_64-linux-gnu/libc_pic.a 之类的文件,这是一个与位置无关的代码的静态库。这可能用于扩展系统的libc.so.6,例如你自己的函数(或你自己的malloc等...)。

在实践中,您最好使用-fPIC 重新编译您的静态库代码;顺便说一句,x86-64 ISA 旨在促进 PIC。

最后,如果您关心优化,这里有many。您是否考虑过使用 gcc -O3 -fPIC -flto 编译和链接?在某些情况下,您可能会考虑使用 -ffast-math(它可以针对 C 标准进行优化),或者将 -O3 替换为 -Ofast

您当然应该使用最近的 GCC 或 Clang 编译器(或最近的专有 icc)。 This old 问题(在您的 cmets 中提到)约为 4.7。当前 2018 年秋季的 GCC 是 GCC 8,并且正在处理 GCC 9(因此应该在 2019 年春季出现)。当前 Clang 是 Clang 7。 编译器在优化方面不断取得进展。

您可能想要下载最新版本的 GCC 或 Clang 的 source 压缩包并在您的计算机上构建它。这是获得这些编译器最新版本的好方法,因为发行版制造商通常更喜欢它们的旧版本(即使与不符合标准的代码也兼容)。

【讨论】:

  • 当然我可以使用fPIC,但我不想减慢静态库中的高性能代码。如果我不需要来自外部的位置无关代码(使用共享库时),我认为可以避免-fPIC,仅通过使用-fPIC 编译的目标文件中定义的接口。所以这不是真的,即使对于不会直接从共享库的用户调用的静态库,我仍然需要它?
  • 您确定-fPIC 会减慢您在x86-64 上的代码吗?你有基准吗?测得的减速是多少? x86-64 ISA 旨在促进 PIC
  • 不,但我读到了 -fPIC 一些优化被禁用。是的,我知道一个人不应该在没有基准测试的情况下尝试优化......
  • 你在哪里读到的?对于什么 ISA?我倾向于认为您的来源是错误的。
猜你喜欢
  • 2017-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-08
  • 1970-01-01
  • 2012-11-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多