当前位置: 首页 > news >正文

target_include_directories对比 PUBLIC / PRIVATE

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 一、表述详解
      • 核心结论
      • 补充核心定义(关键)
  • 二、完整项目示例
    • 1. 项目目录结构
    • 2. 源码文件
      • `include/lib.h`(库的公共接口)
      • `src/lib.cpp`(库的实现文件)
      • `src/main.cpp`(主程序)
    • 3. CMake 构建脚本
      • 写法1:使用 `PUBLIC`(标准正确用法)
      • 写法2:错误演示(改用 `PRIVATE`)
    • 4. 编译与效果测试
      • 编译命令(终端执行)
      • 结果对比
  • 三、`PRIVATE` 的**正确使用场景**
    • 调整后的目录结构
    • 新增文件:`src/private_inc/internal.h`
    • 修改 `src/lib.cpp`
    • 优化后的 CMake 配置
      • 效果
  • 四、总结

通过实操对比PUBLIC/PRIVATE的效果

一、表述详解

cmake_demo/ ├── include/ │ └── lib.h# 带导出宏的头文件├── src/ │ ├── lib.cpp# 动态库实现│ └── main.cpp# 调用方程序└── CMakeLists.txt

核心结论

target_include_directories(mylib PRIVATE 路径)的适用场景:
该头文件路径仅被lib.cpp(库的实现文件)使用,不会被main.cpp(依赖该库的外部代码)包含,此时用PRIVATE
如果外部代码(main.cpp)需要包含这个路径下的头文件(lib.h),必须用PUBLIC,否则外部目标会找不到头文件。


补充核心定义(关键)

作用域适用场景
PUBLIC路径既给lib.cpp用,也给所有依赖 mylib 的目标(如main.cpp)用(接口头文件路径)
PRIVATE路径仅给lib.cpp自用,不传递给外部依赖目标(库内部私有头文件路径)
INTERFACE路径不给自身用,仅传递给外部依赖目标

二、完整项目示例

1. 项目目录结构

采用标准工程规范,公共头文件放在include目录,源文件放在src目录:

cmake_demo/ ├── include/ # 公共头文件目录(外部可访问) │ └── lib.h # 库接口声明 ├── src/ │ ├── lib.cpp # 库实现文件 │ └── main.cpp # 主程序(调用库函数) └── CMakeLists.txt # 构建脚本

2. 源码文件

include/lib.h(库的公共接口)

头文件保护宏防止重复包含,声明加法函数,会被main.cpp直接包含:

#ifndefLIB_H#defineLIB_H// 加法函数声明:对外提供的接口intadd(inta,intb);#endif// LIB_H

src/lib.cpp(库的实现文件)

包含公共头文件,实现加法逻辑:

// 包含库的接口头文件#include"lib.h"// 实现加法函数intadd(inta,intb){returna+b;}

src/main.cpp(主程序)

调用库的add函数,需要包含lib.h

#include<stdio.h>// 包含库的公共头文件#include"lib.h"intmain(){intres=add(10,20);printf("10 + 20 = %d\n",res);return0;}

3. CMake 构建脚本

写法1:使用PUBLIC(标准正确用法)

因为main.cpp需要依赖include路径找到lib.h,因此路径需要传递给外部目标,用PUBLIC

cmake_minimum_required(VERSION 3.15) project(AddLibraryDemo) # C++标准配置 set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) # 1. 创建静态库目标 mylib add_library(mylib src/lib.cpp) # 2. 为库添加头文件路径:PUBLIC 表示路径自身可用,且传递给依赖它的目标 target_include_directories(mylib PUBLIC include) # 3. 创建可执行目标 add_executable(main_app src/main.cpp) # 4. 链接库:main_app 会自动继承 mylib 的 PUBLIC/INTERFACE 头文件路径 target_link_libraries(main_app PRIVATE mylib)

写法2:错误演示(改用PRIVATE

如果我们把PUBLIC改为PRIVATE,代表include路径仅给 mylib 自身使用,不传递

# 仅修改这一行,其余代码不变 target_include_directories(mylib PRIVATE include)

4. 编译与效果测试

编译命令(终端执行)

# 创建构建目录并进入mkdirbuild&&cdbuild# 生成构建文件cmake..# 编译make

结果对比

  1. PUBLIC配置:编译成功,运行./main_app,输出:
    10 + 20 = 30
  2. PRIVATE配置编译直接报错,提示找不到头文件:
    fatal error: lib.h: No such file or directory #include "lib.h"
    原因:main_app无法继承include路径,编译器找不到头文件。

三、PRIVATE正确使用场景

为了让你理解PRIVATE不是无用的,我们扩展场景:给库添加私有内部头文件,仅lib.cpp使用,外部无需访问。

调整后的目录结构

cmake_demo/ ├── include/ # 公共头文件(对外) │ └── lib.h ├── src/ │ ├── private_inc/ # 库私有头文件(仅内部用) │ │ └── internal.h │ ├── lib.cpp │ └── main.cpp └── CMakeLists.txt

新增文件:src/private_inc/internal.h

#ifndefINTERNAL_H#defineINTERNAL_H// 库内部使用的工具函数,不对外部暴露staticintcalc(intx){returnx*2;}#endif

修改src/lib.cpp

#include"lib.h"// 包含私有内部头文件#include"internal.h"intadd(inta,intb){// 调用内部工具函数returncalc(a+b);}

优化后的 CMake 配置

公共路径用PUBLIC,私有路径用PRIVATE

cmake_minimum_required(VERSION 3.15) project(AddLibraryDemo) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) add_library(mylib src/lib.cpp) # 公共头文件:传递给外部依赖目标 target_include_directories(mylib PUBLIC include) # 私有头文件:仅库自身使用,不传递 target_include_directories(mylib PRIVATE src/private_inc) add_executable(main_app src/main.cpp) target_link_libraries(main_app PRIVATE mylib)

效果

  1. main_app能继承include路径,正常找到lib.h
  2. main_app无法访问src/private_inc路径,保证了库内部实现的封装性;
  3. lib.cpp可以同时找到公共头文件和私有头文件。

四、总结

  1. 表述纠正main.cpp依赖该头文件路径时,必须用PUBLIC;仅lib.cpp依赖时,才用PRIVATE
  2. 核心规则
    • 对外暴露的接口头文件路径 →PUBLIC(传递给依赖目标);
    • 库内部私有的实现头文件路径 →PRIVATE(仅自身使用,封装隔离);
  3. 单目标/多目标通用:这套规则是现代CMake的标准规范,无论项目大小都推荐使用,比全局的include_directories更安全、更易维护。
http://www.jsqmd.com/news/347254/

相关文章:

  • YOLO26改进 - 卷积Conv LAE 轻量级自适应提取卷积,从多尺度特征图中获得更多的上下文信息和高分辨率细节
  • CMake制作动态库与静态库对比
  • YOLO26改进 - 卷积Conv MKDC 多核深度卷积块:多分支架构协同捕获局部细节与全局语义,提升特征判别力 ICCV 2025
  • YOLO26改进 - 卷积Conv 增强感受野与多尺度特征捕获:引入RFB感受野块(Receptive Field Block)多分支卷积结构
  • SW草图绘制之倒角和圆角
  • YOLO26改进 - SPPF模块 替代SPPF, Mona多认知视觉适配器(CVPR 2025):打破全参数微调的性能枷锁:即插即用的提点神器
  • YOLO26改进 - SPPF模块 SPPELAN 空间金字塔池化与增强局部注意力:替代SPPF增强多尺度上下文捕获,提升检测精度
  • YOLO26改进 - 卷积Conv 融合多阶门控聚合网络MogaNet与 CA block,提升复杂场景与小目标检测鲁棒性
  • YOLO26改进 - 卷积Conv 即插即用轻量化突破:OREPA在线卷积重参数化,通过动态结构演化实现高效特征提取与自适应优化
  • YOLO26改进 - SPPF模块 替代SPPF,FFocal Modulation焦点调制:即插即用轻量设计优化全局语义捕获
  • YOLO26改进 - SPPF模块 发论文神器!LSKA注意力改进SPPF,增强多尺度特征提取能力,高效涨点!!!
  • 钣金件化学池视觉跟踪系统方案
  • YOLO26改进 - SPPF模块 AIFI基于注意力的尺度内特征交互:替代SPPF构建高效混合编码器,提升模型综合效能
  • 2.5 response资源路径
  • YOLO26改进 - C3k2 C3k2 融合 LSConv (Large-Small Conv)融合大核感知与小核聚合,提升小目标特征判别力 CVPR 2025
  • YOLO26改进 - C2PSA C2PSA融合CPIASA跨范式交互与对齐自注意力机制 交互对齐机制,提升小目标与遮挡目标判别力 ACM MM2025
  • YOLO26改进 - 下采样 轻量化突破:ADown 下采样让 YOLO26 参量减、精度升
  • YOLO26改进 - C3k2 C3k2融合LWGA轻量分组注意力(Light-Weight Grouped Attention):四路径并行架构破解通道冗余难题 AAAI 2026
  • 豆包问答中为何看不到你的品牌?可能是内容“不可见” - 品牌2025
  • YOLO26改进 - C2PSA C2PSA融合DiffAttention差分注意力:轻量级差分计算实现高效特征降噪,提升模型抗干扰能力
  • YOLO26改进 - C3k2融合 C3k2融合Mona多认知视觉适配器:打破全参数微调的性能枷锁:即插即用的提点神器 CVPR 2025
  • YOLO26改进 - C2PSA C2PSA融合Mask Attention掩码注意力,可学习掩码矩阵破解低分辨率特征提取难题 2025 预印
  • 巴菲特的市场看法与经济预测
  • YOLO26 改进 - 注意力机制 空间增强注意力SEAM(Spatially Enhanced Attention Module)提升遮挡场景检测鲁棒性
  • WSL2 完整开发环境配置指南
  • YOLO26改进 - C3k2 C3k2融合HMHA分层多头注意力机制:优化模型在复杂场景下的目标感知能力 CVPR 2025
  • YOLO26改进 - C2PSA C2PSA融合Mona多认知视觉适配器:打破全参数微调的性能枷锁:即插即用的提点神器 CVPR 2025
  • YOLO26 改进 - 注意力机制 Mask Attention掩码注意力,可学习掩码矩阵破解低分辨率特征提取难题 2025 预印
  • YOLO26 改进 - 注意力机制 轴向注意力Axial Attention(Axial Attention)优化高分辨率特征提取
  • 语言模型推理能力的认知负荷评估研究