-fPIC 仅适用于共享库吗?

Is -fPIC for shared libraries ONLY?

我知道 -fPIC 是共享库所必需的,并且知道为什么。

但是,我对这个问题不是很清楚:

在构建可执行文件或静态库时不应该使用 -fPIC 吗?

Should -fPIC never be used during building an executable or a static library?

从不是一个强词,上面的说法是错误的。

使用 -fPIC 构建的代码(稍微)不太理想,那么为什么要将它放入共享库以外的任何地方?

让我们从静态库开始,答案很简单。

假设您想为用户提供一个静态库,该库可以link编辑为可执行文件,进入他们自己的共享库?

在那种情况下,您必须要么给他们 3 个独立的归档库(一个是用 -fPIC 构建的,用于 link 进入共享库,一个是用 -fPIC 构建的-fPIE 用于 link 进入 PIE 可执行文件,还有一个 "regular" ),或者你可以给他们一个单一的存档库(必须有使用 -fPIC 构建的代码)。

现在,您可能会争辩说您应该给他们一个共享库,但这会迫使您的最终用户分发 2 个二进制文件,而他们可能不愿意这样做。

但是假设您想构建一个常规 (non-PIE) 可执行文件。将 -fPIC 中的 link 代码写入此类可执行文件的原因可能是什么?

好吧,假设您处于开发阶段,还不太关心优化代码。进一步假设您想要将代码作为共享库、 作为 PIE 的一部分和 non-PIE 可执行文件进行测试。

在上述条件下,您可以编译代码 3 次(使用和不使用 -fPIC,以及使用 -fPIE), 您可以编译它一次(使用 -fPIC)和 link 它进入所有 3 个共享库,PIE 和 non-PIE 可执行文件。这样做可以节省大量的编译时间和一些构建系统的复杂性。

TL;DR:将 -fPIC 对象放入可执行文件和静态库中有它的位置,您应该了解您这样做的原因(如果您最终这样做)。

更新:

Code in an object file is always relocatable

正确。

is it position-independent code?

否:并非所有可重定位代码都是position-independent。

Position-independent 代码是可重定位代码的 子集 。可重定位代码可以具有适用于 any 部分的重定位。 Position-independent 代码必须 不能 .text(和 .rodata)进行任何重定位。