首页 > 其他分享 >CMake 设置 include 和 link 时的属性

CMake 设置 include 和 link 时的属性

时间:2024-09-12 10:13:42浏览次数:8  
标签:CMake target 目录 目标 link INTERFACE include PUBLIC

CMake 设置 include 和 link 时的属性

在 CMake 中,target_include_directories 和 target_link_libraries 命令使用 PRIVATE、PUBLIC 和 INTERFACE 关键字来控制包含目录和链接库的传递性。

  • PRIVATE:仅对目标自身可见。其他依赖该目标的目标无法访问这些包含目录或链接库。
  • PUBLIC:对目标自身和所有依赖该目标的目标都可见。即,包含目录或链接库会被传递给依赖该目标的所有目标。
  • INTERFACE:仅对依赖该目标的目标可见,目标自身不可见。

举个例子:

# A库
add_library(A ...)
target_include_directories(A PUBLIC include)

# B库依赖于A库
add_library(B ...)
target_link_libraries(B PUBLIC A)

# C库依赖于B库
add_library(C ...)
target_link_libraries(C PRIVATE B)

在这个例子中:

  1. A库的包含目录是include,并且是PUBLIC的,所以任何依赖A的目标都可以访问include目录。
  2. B库依赖于A库,并且是PUBLIC的,所以任何依赖B的目标也可以访问A的包含目录。
  3. C库依赖于B库,并且是PRIVATE的,所以C库本身可以访问B库,但不会将B库传递给其他依赖C的目标。

因此,C库可以访问A库的包含目录,因为B库以PUBLIC方式依赖于A库。但是,如果B库以PRIVATE方式依赖于A库,那么C库将无法访问A库的包含目录。

总结:

  • PRIVATE:仅目标自身可见,不传递。
  • PUBLIC:目标自身和依赖目标都可见,传递。
  • INTERFACE:仅依赖目标可见,不传递给目标自身。

INTERFACE

INTERFACE 属性比较特殊,在 CMake 中,它仅用来指定对依赖目标可见的属性,而对定义这些属性的目标自身不可见。在希望传递某些属性(如 include 目录或者编译选项)给依赖目标,但不希望这些属性影响定义这些属性的目标自身时,特别有用。另外,可以在声明一个库的时候,使用 INTERFACE 关键字来定义该库为一个 INTERFACE 库。INTERFACE 库不生成实际的二进制文件。

以下是INTERFACE关键字的主要用途:

  1. 传递包含目录:当你希望某个库的包含目录仅对依赖它的目标可见,而不影响该库自身的编译。
  2. 传递编译选项:当你希望某些编译选项仅对依赖目标生效,而不影响该库自身的编译。
  3. 传递链接库:当你希望某些链接库仅对依赖目标生效,而不影响该库自身的链接。

举个例子:

# 定义一个接口库
add_library(MyInterfaceLib INTERFACE)

# 设置接口库的包含目录
target_include_directories(MyInterfaceLib INTERFACE ${CMAKE_SOURCE_DIR}/include)

# 设置接口库的编译选项
target_compile_options(MyInterfaceLib INTERFACE -Wall -Wextra)

# 定义一个实际库,依赖于接口库
add_library(MyActualLib src/my_actual_lib.cpp)
target_link_libraries(MyActualLib PUBLIC MyInterfaceLib)

在这个例子中:

  1. MyInterfaceLib是一个接口库,它不会生成任何实际的二进制文件。
  2. MyInterfaceLib的包含目录和编译选项通过INTERFACE关键字指定,这意味着这些属性仅对依赖MyInterfaceLib的目标可见。
  3. MyActualLib依赖于MyInterfaceLib,因此MyActualLib会继承MyInterfaceLib的包含目录和编译选项。

可是看到,INTERFACE 库的作用和 C++中的抽象基类有一些类似,它可以定义公共的编译选项、include 目录等属性,供依赖它的目标继承,但不包含实现,即 INTERFACE 库不生产实际的二进制文件。

而对于非 INTERFACE 库,可以同时使用 PUBLICPRIVATEINTERFACE 来目标设置不同的属性,例如:

# 定义一个普通库
add_library(MyLibrary src/my_library.cpp)

# 设置包含目录
target_include_directories(MyLibrary
    PRIVATE ${CMAKE_SOURCE_DIR}/src/private_include
    PUBLIC ${CMAKE_SOURCE_DIR}/src/public_include
    INTERFACE ${CMAKE_SOURCE_DIR}/src/interface_include
)

# 设置编译选项
target_compile_options(MyLibrary
    PRIVATE -DPRIVATE_DEFINE
    PUBLIC -DPUBLIC_DEFINE
    INTERFACE -DINTERFACE_DEFINE
)

在这个例子中:

PRIVATE 属性(如包含目录和编译选项)仅对 MyLibrary 自身可见,不会传递给依赖 MyLibrary 的目标。
PUBLIC 属性对 MyLibrary 自身和依赖 MyLibrary 的目标都可见,会传递给依赖 MyLibrary 的目标。
INTERFACE 属性仅对依赖 MyLibrary 的目标可见,不会影响 MyLibrary 自身。
总结

include_directories、target_include_directories

设置 include 目录时,一个较为有用的选项是SYSTEM,这会告诉编译器将这些目录视为系统包含目录,从而抑制这些目录中同文件的警告。例如系统引入了更多的编译警告的同时使用了第三方库,为了抑制编译时,编译器对第三方库的代码产生多余的警告,可以在 include 第三方库时,使用SYSTEM选项。

标签:CMake,target,目录,目标,link,INTERFACE,include,PUBLIC
From: https://www.cnblogs.com/tianshihao/p/18409590

相关文章

  • 微信小程序开发系列7----页面配置--WXML的include用法
       传递变量   模板不能引用 ......
  • 通过LinkedIn的思想领袖广告提升有机帖子效果,降低每次结果成本
    通过在LinkedIn上发布能够吸引互动(如点赞和评论)的自然帖子,并添加一个号召性用语(CTA)将其提升为思想领袖广告,Fame降低了每次结果的成本。目录摘要营销策略是什么?结果是什么?为什么这行得通?摘要营销策略是什么?在LinkedIn上,如果一个广告有许多互动,如点赞和评论,你将为你的投入获......
  • 实例讲解Simulink CAN通讯丢失故障判定模型搭建及仿真测试验证方法
    在电动汽车VCU软件开发中,要开发故障诊断模块,故障诊断类型中CAN报文通讯丢失的判定是非常重要的一个,当检测到某个控制器CAN报文通讯丢失,即接收不到该控制器的有效CAN信号,需要根据通讯丢失的判断作出相应的故障处理,以保证整车行车安全。本文通过ABS通讯丢失Simulink模块的搭建,介......
  • 12-LinkedHashSet
    LinkedHashSetHashSet得到的数据是无序的--->能不能得到的数据是有序的,嫩不能按照输入原序输出?---->LinkedHashSet特点唯一有序(按照输入顺序输出)多了一个总链表,按装入顺序串在一起原理其实就是在HashSet的基础上,多了一个总的链表,这个总链表将放入的元素串在一起,方便有......
  • 使用ChainLink预言机聚合器合约
    有了使用Hardhatforking功能模拟主网的基础,我们来看一下如何在链上使用预言机聚合器合约来获取某个数字资产当前价格。代码https://solidity-by-example.org/defi/chainlink-price-oracle///SPDX-License-Identifier:MITpragmasolidity^0.8.24;contractChainlinkPrice......
  • CMakeLists.txt 和 Makefile
    CMakeLists.txt和Makefile都是用于自动化编译和构建软件项目的配置文件,但它们在构建系统中扮演不同的角色,并且使用不同的构建工具。CMakeLists.txtCMakeLists.txt 文件是CMake构建系统的配置文件。CMake是一个跨平台的自动化构建系统,它使用 CMakeLists.txt 文件来生......
  • HTML的<link>元素
    <link>定义当前文档和外部资源之间的关系。最常用于链接到外部样式表或向网站添加图标。可以在head元素、body元素中使用,但是最好在head元素中使用。支持HTML全局属性和事件属性。例子1:链接外部样式表<head><linkrel="stylesheet"type="text/css"href="mystyle.css"></head> 例......
  • 14、Flink SQL 的 事件时间详解
    事件时间事件时间允许程序按照数据中包含的时间来处理,这样可以在有乱序或者晚到的数据的情况下产生一致的处理结果,它可以保证从外部存储读取数据后产生可以复现(replayable)的结果。事件时间可以让程序在流式和批式作业中使用同样的语法,在流式程序中的事件时间属性,在批式程......
  • 运用DBLINK与数据泵导数据时报错ORA-39006、ORA-39113、PLS-00352、PLS-00201、ORA-39
    问题描述:运用DBLINK与数据泵导数据时报错ORA-39006、ORA-39113、PLS-00352、PLS-00201、ORA-39097,如下所示:数据库:源端oracle12.2.0.1目标端:oracle12.2.0.11、问题重现[oracle@hisdb1scripts]$tail-500fnohup.outImport:Release12.2.0.1.0-ProductiononFriSep......
  • CMake中添加Qt模块的合理方法
    https://www.jianshu.com/p/7eeb6f79a275转载自这里用CMake来组织的工程中要用Qt首先要设置、找到Qt相关模块。主要是通过find_package这个CMake命令。但网上很多教程都过时了,或者不够清晰灵活。因为这部分很常用,所以特别用一篇文章把我们目前在生产环境中使用的方法给大家介......