cmake:target属性POSITION_INDEPENDENT_CODE和INTERFACE_POSITION_INDEPENDENT_CODE的区别

2023-09-21 12:04:11

cmake定义的target有两个名字类似的属性:POSITION_INDEPENDENT_CODEINTERFACE_POSITION_INDEPENDENT_CODE,本文说明它们的含义和区别

-fPIC

介绍POSITION_INDEPENDENT_CODEINTERFACE_POSITION_INDEPENDENT_CODE属性前先介绍一下-fPIC编译选项。
-fPIC是gcc编译器的编译参数,以下是机器人告诉我的关于-fPIC参数的作用

在GCC编译器中, -fPIC 参数是指生成位置无关代码(Position Independent Code,PIC)。位置无关代码是一种可在内存中的任何位置加载和执行的代码。它通常用于动态链接库(shared library)的编译。

使用 -fPIC 参数编译代码时,生成的目标文件中的代码和数据引用都使用相对地址,而不是绝对地址。这样,当目标文件被加载到内存中时,它可以被放置在任何可用的内存地址上,而不会发生地址冲突。

通过使用位置无关代码,可以使得动态链接库在不同的内存地址空间中被加载和共享,提供更高的灵活性和可移植性。这对于操作系统和应用程序来说是非常重要的,因为它们可以在不同的环境中加载和使用这些动态链接库,而无需担心地址冲突和重新编译的问题。

总结来说, -fPIC 参数的作用是生成位置无关代码,用于编译动态链接库,以提供更高的灵活性和可移植性。

可以看出-fPIC参数是用于动态库的编译参数。

POSITION_INDEPENDENT_CODE

定义 -fPIC 参数最直接的方式是通过CMAKE_CXX_FLAGSCMAKE_C_FLAGS参数定义,
示例如下,因为它只是clang和gcc才有的参数所以在设置-fPIC参数的时候需要判断编译器

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
   set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
endif()

但这样在跨平台项目编译时需要更多的维护工作量,为了让CMakeLists.txt脚本更简洁,减少编译器无关性,通过POSITION_INDEPENDENT_CODE属性来定义-fPIC参数是推荐的方式:
POSITION_INDEPENDENT_CODE是cmake为target定义的属性
可以通过set_property,set_target_properties函数来定义POSITION_INDEPENDENT_CODE属性

## set_property示例
set_property(TARGET my_target PROPERTY POSITION_INDEPENDENT_CODE ON)
## set_target_properties 示例
set_target_properties (my_target PROPERTIES POSITION_INDEPENDENT_CODE ON)

根据cmake官方文档说明,当target为动态库时POSITION_INDEPENDENT_CODE 默认值为True,否则为静态库时默认为False;
参见 POSITION_INDEPENDENT_CODE

CMAKE_POSITION_INDEPENDENT_CODE

注意POSITION_INDEPENDENT_CODE是target的属性,所以set_property,set_target_properties 调用只对target有效,而通过CMAKE_CXX_FLAGSCMAKE_C_FLAGS参数定义定义 -fPIC 参数对所有target有效。如果也希望一次定义所有target的POSITION_INDEPENDENT_CODE属性,则可以通过设置CMAKE_POSITION_INDEPENDENT_CODE变量来实现,用于定义所有target的POSITION_INDEPENDENT_CODE属性的默认值

set(CMAKE_POSITION_INDEPENDENT_CODE ON)

INTERFACE_POSITION_INDEPENDENT_CODE

INTERFACE_POSITION_INDEPENDENT_CODE也是target的属性,但它的作用与POSITION_INDEPENDENT_CODE不同
INTERFACE_POSITION_INDEPENDENT_CODE 属性通知消费者(即依赖于当前target的target)是否需要将他们的 POSITION_INDEPENDENT_CODE 属性设置为ON。如果该属性被设置为ON,那么所有消费者的 POSITION_INDEPENDENT_CODE 属性也将被设置为ON。同样地,如果该属性被设置为OFF,那么所有消费者的 POSITION_INDEPENDENT_CODE 属性也将被设置为OFF。如果该属性未定义,那么消费者将通过其他方式确定他们的 POSITION_INDEPENDENT_CODE 属性。
总结就是INTERFACE_POSITION_INDEPENDENT_CODE 用于确保消费者与链接的目标的POSITION_INDEPENDENT_CODE 属性保持一致性。

简单来说就是
如果一个target定义了INTERFACE_POSITION_INDEPENDENT_CODE属性并不会影响自己的POSITION_INDEPENDENT_CODE属性,而是会影响依赖它的Target的POSITION_INDEPENDENT_CODE属性

add_library(a STATIC a.cpp)
set_target_properties (a PROPERTIES 
	POSITION_INDEPENDENT_CODE ON 
	INTERFACE_POSITION_INDEPENDENT_CODE ON)
add_library(b SHARED b.cpp)

如上示例中,静态库a设置了POSITION_INDEPENDENT_CODEONINTERFACE_POSITION_INDEPENDENT_CODEON,因为INTERFACE_POSITION_INDEPENDENT_CODE 的传递作用,
动态库b的POSITION_INDEPENDENT_CODE属性自动为ON

INTERFACE_POSITION_INDEPENDENT_CODE 属性实际只有静态库需要设置,对于动态库不需要设置该属性,因为动态库不需要依赖库保存位置无关代码(PIC)一致性

位置无关代码一致性要求

前面说了-fPIC参数是用于动态库的编译参数。但对于静态库有时也需要指定-fPIC编译出位置无关代码,因为一个动态库连接静态库时,如果其连接的静态库都不是编译为位置无关代码代码(-fPIC),则在连接阶段可能会报错:

/usr/bin/ld: …/…/static.a(file.cpp.o): relocation R_X86_64_TPOFF32 against symbol `_ZGVZN6spdlog7details2os9thread_idEvE3tid’ can not be used when making a shared object; recompile with -fPIC

参考资料

https://cmake.org/cmake/help/latest/prop_tgt/POSITION_INDEPENDENT_CODE.html
https://cmake.org/cmake/help/latest/prop_tgt/INTERFACE_POSITION_INDEPENDENT_CODE.html
https://cmake.org/cmake/help/latest/variable/CMAKE_POSITION_INDEPENDENT_CODE.html

更多推荐

4. algorithm

algorithm书写1.algorithm2.algorithm2e1.algorithm在LaTeX中,要显示算法,您可以使用algorithm宏包来排版算法,并使用algorithmic宏包来编写算法的伪代码。以下是显示算法的基本步骤:导入宏包:在LaTeX文档的导言区(preamble)中,导入algorith

idea集成tomcat(Smart Tomcate插件安装)

当我们在tomcat上部署好一个webapp后,如果我们要修改代码,就需要重新进行打包和部署,但往往在工作中是需要频繁修改代码,然后再查看成果的,就需要反复的进行打包和部署的过程,这是很麻烦的通过SmartTomcate插件我们就能解决这个问题,可以直接使用idea图形化界面把代码部署到tomcat上达成“一键打包&部

Windows服务器设置Nginx实现分布式服务

1.安装Nginx下载Nginx-1.16.1版本。解压到如下目录:设置环境变量:检查版本:启动nginx.exe,出现黑框一闪而过,进程中出现如下情况代表启动成功:2.搭建模拟HTTP服务下载wiremock-standalone-2.25.1.jar,可以使用Maven配置pom.xml下载。注意下载standal

JavaWeb后端开发 JWT令牌解析 登录校验 通用模板/SpringBoot整合

目录实现思路相关技术的解析​编辑会话跟踪三个方案JWT令牌技术​生成令牌校验令牌登录下发令牌实现思路通过登录成功的标记来检测,在每个接口前做一个标记判断是否登录,若没登录则返回错误信息,并使前端退出.但这样较为繁琐,因此我们可以通过一种统一拦截的技术来拦截所有请求.相关技术的解析会话跟踪的三个方案1.访问cookie的

Nginx替代产品-Tengine健康检测

1、官网地址官网地址:TheTengineWebServer文档地址:文档-TheTengineWebServer健康检测模块:ngx_http_upstream_check_module-TheTengineWebServer2、安装下载wgethttps://tengine.taobao.org/download/

数据中心防雷机柜PDU产品应该怎么选?

PDU防雷插座是针对标准机柜上安装而设计,主要保护机柜内通信、电子等重要设备,避免因过电压和雷电感应而造成设备损坏。该类型PDU将防雷器与电源插板完美组合,配有多路输出插孔,兼容多国插头标准,可同时保护多路电源,使用安全可靠,简单方便,可更换式防雷模块、维护方便等优点。随着现代科技的发展和社会的进步,各行各业在不断地引

E. Moment of Bloom

Problem-E-Codeforces思路:这个题看到之后想到了不可能的情况,就是如果度为奇数就一定不可能实现都是偶数,但是后面就不知道怎么搞了。正解是欧拉定理的应用把算是,首先对于给定的q个要求,我们从a->b连一条边,如果此时生成的图由许多个欧拉回路组成,并且我们还知道给定的这个图是联通的,那么我们就可以生成一颗

阿里云产品试用系列-函数计算 FC

函数计算(FunctionCompute)是一个事件驱动的全托管Serverless计算服务,您无需管理服务器等基础设施,只需编写代码并上传,函数计算会为您准备好计算资源,并以弹性、可靠的方式运行您的代码。如上所示,在阿里云首页访问免费试用函数计算FC云计算产品如上所示,设置内存资源以及计算资源的容量如上所示,在阿里云

如何获取美团的热门商品和服务

导语美团是中国最大的生活服务平台之一,提供了各种各样的商品和服务,如美食、酒店、旅游、电影、娱乐等。如果你想了解美团的热门商品和服务,你可以使用爬虫技术来获取它们。本文将介绍如何使用Python和BeautifulSoup库来编写一个简单的爬虫程序,以及如何使用爬虫代理来提高爬虫的效率和稳定性。概述爬虫技术是一种通过网

【qiankun乾坤】从0到1搭建微前端

微前端是一种将一个大型单体应用拆分成多个小型应用的架构方式。它可以让不同的团队独立开发部署自己的应用,同时这些应用可以集成到一个统一的底座应用中,对用户来说就是一个完整的应用。qiankun是阿里开源的一个微前端实现框架,可以帮助我们比较容易地实现微前端架构。下面来介绍如何从0到1使用qiankun+vue搭建一个微前

单元测试(JUint)

单元测试概述单元测试就是方法测试。Junit单元测试框架JUnit是使用Java语言实现的单元测试框架,它是开源的,Java开发者都应当学习并使用JUnit编写单元测试。此外,几乎所有的IDE工具都集成了JUnit,这样我们就可以直接在IDE中编写并运行JUnit测试,JUnit目前最新版本是5。JUnit优点JUni

热文推荐