cmake编译成.so文件_cmake:`.rodata' can not be used...

ec42a0678cdd9e492491fef17edf7ab2.png

该文章使用这一章的测试工程

发现问题

为了部署方便,现让所有的模块生成静态库(.a)。即, libhello-world.so ---> libhello-world.a, libhello.so ---> libhello.a, libworld.so ---> libworld.a。(静态库和动态库的优缺点)

如果将上述三个动态库同时改为静态库是没问题的,编译、执行,很顺利,目的已达到。但是,在测试过程中,有一个场景会产生问题。

场景如下(注意 libhello):

                              ├────libhello.a
可执行文件────libhello-world.so
                              ├────libworld.so

在只将 libhello.so 改为 libhello.a,而 libhello-world.so 为动态库时,编译过程中产生如下错误信息:

Linking C shared library libhello-world.so
/usr/bin/ld: hello/libhello.a(hello.c.o): relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
hello/libhello.a: 无法添加符号: 错误的值
collect2: error: ld returned 1 exit status
hello-world/CMakeFiles/hello-world.dir/build.make:85: recipe for target 'hello-world/libhello-world.so' failed
make[2]: *** [hello-world/libhello-world.so] Error 1
CMakeFiles/Makefile2:133: recipe for target 'hello-world/CMakeFiles/hello-world.dir/all' failed
make[1]: *** [hello-world/CMakeFiles/hello-world.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2

产生的原因很明确:can not be used when making a shared object——在生成动态库(libhello-world.so)的过程中产生的错误。解决方法是:recompile with -fPIC。什么意思?"-fPIC" 是什么东西?应该把它放在哪?

说明

PIC:position independent code,地址无关码。

生成动态库时必须使用地址无关码。因为在动态库被装载时,其地址是不确定的。因此在用静态库生成动态库时需要将静态库“转换”为地址无关码。

-fPIC:gcc 编译源文件生成目标文件时通过该参数使生成的目标文件为地址无关码。

cmake 生成地址无关码

以下为cmake生成地址无关码的几种方式:

set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
add_compile_options(-fPIC)
target_compile_options(${PROJECT_NAME} PRIVATE -fPIC)
set_property(TARGET lib1 PROPERTY POSITION_INDEPENDENT_CODE ON)

在这里,我推荐最后两种方式:target_compile_options()set_property()。因为这两个命令都指明了目标文件,不会对其他目标文件有影响。

注:cmake 生成动态库(.so)时会自动指定 -fPIC

参考

https://stackoverflow.com/questions/38296756/what-is-the-idiomatic-way-in-cmake-to-add-the-fpic-compiler-option

https://stackoverflow.com/questions/19364969/compilation-fails-with-relocation-r-x86-64-32-against-rodata-str1-8-can-not

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值