【问题标题】:Interaction of fno-exceptions and POSITION INDEPENDENT CODEfno-exceptions 和 POSITION INDEPENDENT CODE 的交互
【发布时间】:2020-11-10 08:46:52
【问题描述】:

我在构建动态库时遇到了一个相当奇怪的问题。以下是一个小例子的详细信息:

一个名为static.h 的简单文件,其内容是:

#pragma once

#include <string>

std::string static_speak();

static.cpp 看起来像这样:

#include "static.h"

std::string static_speak() {
  return "I am static";
}

可以用这两个文件(使用cmake)构建一个静态库:

add_library(static
  static.cpp
)

现在,考虑另一个名为 shared.cpp 的文件,其内容是:

#include "static.h"

std::string dynamic_speak() {
  return static_speak() + " I am dynamic";
}

可以尝试构建一个动态库(再次使用 cmake):

add_library(shared SHARED
  shared.cpp
)
target_link_libraries(shared PRIVATE
  static
)

当尝试构建上述内容时,会遇到以下错误:

[4/4] Linking CXX shared library libshared.so
FAILED: libshared.so
: && /opt/vatic/bin/clang++ -fPIC -g   -shared -Wl,-soname,libshared.so -o libshared.so CMakeFiles/shared.dir/shared.cpp.o  libstatic.a && :                                 
/usr/bin/ld: libstatic.a(static.cpp.o): relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a shared object; recompile with -fPIC                    
/usr/bin/ld: final link failed: Nonrepresentable section on output
clang-10: error: linker command failed with exit code 1 (use -v to see invocation)
ninja: build stopped: subcommand failed.

这是有道理的。我们没有用POSITION_INDEPENDENT_CODE 编译static。这很容易通过以下方式解决:

add_library(static
  static.cpp
)
set_target_properties(static
  PROPERTIES
  POSITION_INDEPENDENT_CODE ON
)

当编译 shared 库时,现在一切正常。

现在问题来了。假设我没有启用POSITION_INDEPENDENT_CODE,而是在我的代码中禁用了异常(!):

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions")

现在,当我尝试编译 shared 时,一切正常!! 异常和 fPIC 是如何相互关联的?

这里是重现问题的 repo: https://github.com/skgbanga/shared

【问题讨论】:

  • 附带说明,staticshared 是有问题的名称...尝试使用其他名称...
  • @OrenIshShalom 我使用这些名称认为它们更好地传达了问题的意图。很好奇为什么它们会出现问题?

标签: c++ cmake shared-libraries


【解决方案1】:

异常和 fPIC 是如何相互关联的?

他们不是(大部分)。

发生的情况是使用-fno-exceptions 进行编译会更改重定位(不再引用某些与异常相关的数据),因此,在链接时没有导致错误的重定位.

您可以通过使用和不使用-fno-exceptions 进行构建并比较objdump -dr CMakeFiles/static.dir/static.cpp.o 的输出来确认这一点。

附:我无法使用g++ (Debian 9.3.0-8) 重现您的问题,因为它默认使用-fPIE 构建,并且两个链接都成功。

如果我添加-fno-pie,那么两个链接都会以同样的方式失败。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多