fno-exceptions 和 POSITION INDEPENDENT CODE 的交互
Interaction of fno-exceptions and POSITION INDEPENDENT CODE
我 运行 在构建动态库时遇到了一个相当奇怪的问题。以下是一个小例子的详细信息:
一个名为 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 如何相互关联?
这是重现问题的回购协议:
https://github.com/skgbanga/shared
How are exceptions and fPIC related to each other?
他们不是(大部分)。
用-fno-exceptions
编译会改变重定位(不再引用某些与异常相关的数据),因此,没有重定位这会在 link 时导致错误。
您可以通过使用和不使用 -fno-exceptions
构建并比较 objdump -dr CMakeFiles/static.dir/static.cpp.o
.
的输出来确认这一点
P.S。我无法使用 g++ (Debian 9.3.0-8)
重现您的问题,因为它默认使用 -fPIE
构建,并且两个 link 都成功。
如果我添加 -fno-pie
,那么两个 link 都会以同样的方式失败。
我 运行 在构建动态库时遇到了一个相当奇怪的问题。以下是一个小例子的详细信息:
一个名为 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 如何相互关联?
这是重现问题的回购协议: https://github.com/skgbanga/shared
How are exceptions and fPIC related to each other?
他们不是(大部分)。
用-fno-exceptions
编译会改变重定位(不再引用某些与异常相关的数据),因此,没有重定位这会在 link 时导致错误。
您可以通过使用和不使用 -fno-exceptions
构建并比较 objdump -dr CMakeFiles/static.dir/static.cpp.o
.
P.S。我无法使用 g++ (Debian 9.3.0-8)
重现您的问题,因为它默认使用 -fPIE
构建,并且两个 link 都成功。
如果我添加 -fno-pie
,那么两个 link 都会以同样的方式失败。