CMake 中的 PUBLIC,PRIVATE,INTERFACE

本文详细介绍了CMake中target_link_libraries命令的PUBLIC, PRIVATE, INTERFACE三个关键字的区别。PRIVATE依赖只影响直接链接的目标,INTERFACE依赖则会传播给链接该目标的所有目标,而PUBLIC依赖同时具备两者特性。通过这三个关键字,可以精确控制库的依赖传播。建议在项目中合理使用以避免不必要的目录包含和链接。
部署运行你感兴趣的模型镜像

一、概述

CMake中经常会使用 target_**() 相关命令,target_**() 命令支持通过 PUBLICPRIVATE 和 INTERFACE 关键字来控制传播。本文主要介绍下这三个关键字的区别。

二、解释

以 target_link_libraries(A B) 命令为例,从理解的角度解释:

  • PRIVATE 依赖项 B 仅链接到目标 A,若有 C 链接了目标 A,C 不链接依赖项 B 。
  • INTERFACE 依赖项 B 并不链接到目标 A,若有 C 链接了目标 A,C 会链接依赖项 B 。
  • PUBLIC 依赖项 B 链接到目标 A,若有 C 链接了目标 A,C 也会链接依赖项 B 。

从使用的角度解释,若有 C 链接了目标 A :

  • 如果依赖项 B 仅用于目标 A 的实现,且不在头文件中提供给 C 使用,使用 PRIVATE 。
  • 如果依赖项 B 不用于目标 A 的实现,仅在头文件中作为接口提供给 C 使用,使用 INTERFACE 。
  • 如果依赖项 B 不仅用于目标 A 的实现,而且在头文件提供给 C 使用,使用 PUBLIC 。

例 子

举一个简单的例子说明一下

add_library(C c.cpp)
add_library(D d.cpp)

add_library(B b.cpp)
target_link_libraries(B PUBLIC C)
target_link_libraries(B PRIVATE D)

add_executable(A a.cpp)
target_link_libraries(A B)

因为 C 是 B 的 PUBLIC 依赖项,所以其会被传播到 A 。
因为 D 是 B 的 PRIVATE 依赖项,所以其不会传播到 A 。

三、补充

这里补充下使用 target_**()相关命令,有无 target 的区别。

以 target_include_directories() 命令为例,include_directories(dir) 是一个全局设置,其会将 dir 添加到当前 CMakeLists 文件中每个目标的 INCLUDE_DIRECTORIES 属性中。即当前 CMakeLists 文件其下所有的子目录都会添加 dir 目录。

因此,建议使用有 target 的命令来减少不必要或多余的目录包含和链接。

转载:CMake 中的 PUBLIC,PRIVATE,INTERFACE - 简书

(SAW:Game Over!)

您可能感兴趣的与本文相关的镜像

ACE-Step

ACE-Step

音乐合成
ACE-Step

ACE-Step是由中国团队阶跃星辰(StepFun)与ACE Studio联手打造的开源音乐生成模型。 它拥有3.5B参数量,支持快速高质量生成、强可控性和易于拓展的特点。 最厉害的是,它可以生成多种语言的歌曲,包括但不限于中文、英文、日文等19种语言

### CMake 中 `target_include_directories` 的 PRIVATEPUBLIC INTERFACE 的作用及区别CMake 中,`target_include_directories` 是用于为特定目标(如可执行文件或库)指定头文件路径的命令。该命令支持三种权限修饰符:`PRIVATE`、`PUBLIC` `INTERFACE`。这些修饰符决定了头文件路径的作用范围可见性。 #### 1. `PRIVATE` - **作用**:当目标自身需要此头文件路径时使用。 - **可见性**:仅对定义的目标本身生效,不会传递给其他依赖此目标的目标。 - **使用场景**:适用于目标内部实现所需的头文件路径,而不希望这些路径暴露给其他目标的情况。 - **示例代码**: ```cmake add_library(my_lib STATIC my_lib.cpp) target_include_directories(my_lib PRIVATE ${CMAKE_SOURCE_DIR}/include/private) # 仅为 my_lib 提供头文件路径[^3] ``` #### 2. `PUBLIC` - **作用**:当目标自身或其他目标链接了这个目标时使用。 - **可见性**:不仅对定义的目标本身生效,还会传递给所有直接或间接依赖此目标的目标。 - **使用场景**:适用于目标的公共接口需要访问某些头文件路径的情况,同时这些路径也需要被其他依赖此目标的目标共享。 - **示例代码**: ```cmake add_library(my_lib SHARED my_lib.cpp) target_include_directories(my_lib PUBLIC ${CMAKE_SOURCE_DIR}/include/public) # 为 my_lib 及其依赖者提供头文件路径[^3] ``` #### 3. `INTERFACE` - **作用**:当目标自身不需要此头文件路径,但其他目标链接了这个目标时使用。 - **可见性**:仅对依赖此目标的其他目标生效,不对定义的目标本身生效。 - **使用场景**:适用于目标仅作为接口存在,其头文件路径仅供其他目标使用的情况。 - **示例代码**: ```cmake add_library(my_interface INTERFACE) target_include_directories(my_interface INTERFACE ${CMAKE_SOURCE_DIR}/include/interface) # 仅为依赖 my_interface 的目标提供头文件路径[^3] ``` #### 区别总结 | 权限修饰符 | 对定义目标的影响 | 对依赖目标的影响 | |------------|-------------------|-------------------| | `PRIVATE` | 有效 | 无效 | | `PUBLIC` | 有效 | 有效 | | `INTERFACE`| 无效 | 有效 | #### 使用场景分析 - **`PRIVATE`**:适用于目标的私有实现部分,例如静态库的内部实现细节。 - **`PUBLIC`**:适用于动态库或需要公开接口的静态库,确保依赖者能够正确编译。 - **`INTERFACE`**:适用于纯接口库(如 C++ 中的头文件库),不包含任何实现,仅提供接口定义。 --- ### 示例代码 以下是一个完整的示例,展示如何在不同场景下使用 `PRIVATE`、`PUBLIC` `INTERFACE`: ```cmake cmake_minimum_required(VERSION 3.10) project(MyProject) # 定义一个静态库,包含私有头文件路径 add_library(private_lib STATIC private.cpp) target_include_directories(private_lib PRIVATE ${CMAKE_SOURCE_DIR}/include/private) # 定义一个动态库,包含公共头文件路径 add_library(public_lib SHARED public.cpp) target_include_directories(public_lib PUBLIC ${CMAKE_SOURCE_DIR}/include/public) # 定义一个接口库,仅提供接口头文件路径 add_library(interface_lib INTERFACE) target_include_directories(interface_lib INTERFACE ${CMAKE_SOURCE_DIR}/include/interface) # 定义一个可执行文件,链接上述库 add_executable(my_app main.cpp) target_link_libraries(my_app PRIVATE private_lib) target_link_libraries(my_app PUBLIC public_lib) target_link_libraries(my_app INTERFACE interface_lib) ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值