CMake编译中target_link_libraries中属性PRIVATE、PUBLIC、INTERFACE含义

当创建动态库时,

  • 如果源文件(例如CPP)中包含第三方头文件,但是头文件(例如hpp)中不包含该第三方文件头,采用PRIVATE。
  • 如果源文件和头文件中都包含该第三方文件头,采用PUBLIC。
  • 如果头文件中包含该第三方文件头,但是源文件(例如CPP)中不包含,采用 INTERFACE

原文:CMake target_link_libraries Interface Dependencies

http://stackoverflow.com/questions/26037954/cmake-target-link-libraries-interface-dependencies

其他属性可以参考http://www.cmake.org/cmake/help/v3.0/manual/cmake-buildsystem.7.html#transitive-usage-requirements

<think>我们正在讨论CMake中的`target_link_libraries`命令,特别是链接作用域选项(PRIVATE, PUBLIC, INTERFACE)的区别以及默认值。 根据引用[1]:当不明确指定链接类型(publicprivateinterface)时,CMake 默认使用 PRIVATE 链接类型。 引用[2]提供了命令的格式:`target_link_libraries(targetName <PRIVATE|PUBLIC|INTERFACE> item1 ...)` 现在,我们详细解释这三个作用域的区别: 1. **PRIVATE**:表示依赖项仅用于构建当前目标(target),不会传递给依赖当前目标的其他目标。即,链接的库仅用于当前目标的实现,不会暴露给使用该目标的其他目标。 例如(引用[4]):在构建`hello-world`库时,如果只在源文件(如`hello_world.c`)中使用了某个库(如`hello`),而在公开头文件(`hello_world.h`)中未使用,且使用`hello-world`库的其他目标(如`main`)不需要知道`hello`库的存在,则使用PRIVATE。 2. **INTERFACE**:表示依赖项不会用于构建当前目标,但会传递给依赖当前目标的其他目标。即,当前目标本身不使用该库,但使用当前目标的其他目标需要链接该库。 例如:如果当前目标是一个头文件库(没有源文件,只有头文件),那么它可能要求使用它的目标链接某些库,这时就可以用INTERFACE。 3. **PUBLIC**:是PRIVATEINTERFACE的组合。表示依赖项既用于构建当前目标,也会传递给依赖当前目标的其他目标。即,当前目标在实现中使用该库,并且其头文件也使用了该库(因此使用当前目标的其他目标也需要该库)。 例如(引用[3]):在构建`hello-world`库时,如果源文件(`hello_world.c`)和公开头文件(`hello_world.h`)都使用了`hello`库,并且使用`hello-world`库的`main`也需要使用`hello`库的功能,则使用PUBLIC。 总结: - **PRIVATE**:仅构建当前目标时使用。 - **INTERFACE**:仅用于依赖当前目标的目标(当前目标自身不使用)。 - **PUBLIC**:既用于构建当前目标,也用于依赖当前目标的目标。 另外,引用[5]提到了一些CMake变量,但这个问题主要关注链接作用域,所以这里不展开。 **默认值**:如果不指定作用域,则默认为PRIVATE(引用[1])。 因此,在编写CMakeLists.txt时,应根据目标之间的依赖关系选择合适的作用域,以确保依赖关系正确传递,避免链接错误或过度暴露依赖。 §§相关问题§§ 1. 在CMake中,除了`target_link_libraries`,还有哪些命令可以使用PRIVATEPUBLICINTERFACE作用域? 2. 如何正确使用`target_include_directories`命令的作用域选项? 3. 在大型项目中,如何管理CMake目标之间的依赖关系以避免循环依赖? 4. CMake中的目标属性(如INCLUDE_DIRECTORIES、LINK_LIBRARIES)是如何被作用域选项影响的?</think>### CMake中`target_link_libraries`的作用域选项详解 在CMake中,`target_link_libraries`命令用于指定目标(可执行文件或库)的链接依赖关系,其作用域选项(`PRIVATE`、`PUBLIC`、`INTERFACE`)控制依赖项的传递性: #### 1. **默认作用域:`PRIVATE`** - 当未显式指定作用域时(如`target_link_libraries(my_target libA)`),CMake默认使用`PRIVATE`[^1]。 - **行为**:依赖项`libA`仅用于构建`my_target`,**不会**传递给链接`my_target`的其他目标。 - **适用场景**:依赖项仅在当前目标的源文件中使用,且不暴露给外部调用者。 ```cmake # 示例:libA仅在my_target.c中使用,外部无需感知 target_link_libraries(my_target PRIVATE libA) # 默认可省略PRIVATE ``` #### 2. **作用域区别** | 作用域 | 当前目标是否使用依赖 | 依赖是否传递给下游目标 | 典型场景 | |-------------|----------------------|------------------------|--------------------------------------------------------------------------| | `PRIVATE` | ✔️ | ❌ | 依赖仅用于实现内部逻辑(如`.c`文件使用)[^4] | | `INTERFACE` | ❌ | ✔️ | 依赖仅通过头文件暴露给下游(如头文件库)[^3] | | `PUBLIC` | ✔️ | ✔️ | 依赖同时用于内部实现和对外接口(如头文件+源文件均使用依赖)[^3] | #### 3. **关键差异示例 - **`PUBLIC` vs `PRIVATE`**: ```cmake # 若my_target.h中声明了libB的函数,my_target.c中实现了该函数 target_link_libraries(my_target PUBLIC libB) # 下游链接my_target时自动获得libB ``` ```cmake # 若libC仅在my_target.c内部使用 target_link_libraries(my_target PRIVATE libC) # 下游无需知道libC存在[^4] ``` - **`INTERFACE`**: ```cmake # 头文件库:my_header_lib.h直接包含libD的头文件 target_link_libraries(my_header_lib INTERFACE libD) # 下游链接时需libD[^3] ``` #### 4. **作用域对包含路径的影响** 作用域选项同样适用于`target_include_directories`: ```cmake # 下游目标需包含libE的头文件 target_include_directories(my_target PUBLIC path/to/libE/include) ``` > ⚠️ **错误使用后果** > 误用`PRIVATE`可能导致下游目标链接失败(缺少依赖);误用`PUBLIC`可能导致依赖过度暴露,增加编译耦合性[^2][^3]。 ---
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值