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

深入理解 CMake 中的 INCLUDE_DIRECTORIES 与 target_include_directories

在使用 CMake 构建系统时,指定头文件的包含路径是非常常见的一步。对于这个任务,CMake 提供了两种主要的命令:INCLUDE_DIRECTORIEStarget_include_directories。虽然它们看似类似,但它们的作用范围、应用方式以及适用场景却有很大差别。

1. 什么是头文件包含目录?

在编译 C++ 项目时,头文件提供了声明和接口,是源代码文件间相互引用的关键部分。为了告诉编译器去哪里查找这些头文件,通常需要指定一个或多个包含目录(include directories)。如果没有正确设置头文件路径,编译器会报出类似 "file not found" 的错误。因此,如何有效管理和设置这些路径对于构建项目至关重要。

CMake 作为一个跨平台的构建系统,提供了多种方式来为项目设置包含目录,最常用的就是 INCLUDE_DIRECTORIEStarget_include_directories

2. INCLUDE_DIRECTORIES —— 全局包含目录

INCLUDE_DIRECTORIES 是 CMake 中最早的用于设置包含路径的命令,它的效果是全局性的。也就是说,当你在 CMake 文件中调用 INCLUDE_DIRECTORIES 时,它会将指定的包含路径应用到当前作用域下的所有目标(targets)。所有在该命令之后的目标都会继承这些包含路径。

语法:

INCLUDE_DIRECTORIES(<directories>)

使用示例:

INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)

这条指令会将项目根目录下的 include 目录添加为全局的包含目录。这样,所有的目标(如库、可执行文件)都可以从这个目录中查找头文件。

适用场景:

  • 小型项目:在简单项目中,只有少量的源文件和库,头文件目录也很集中。此时使用 INCLUDE_DIRECTORIES 是一个快速且方便的选择。
  • 简单的全局依赖:如果项目中的所有目标都依赖于同一组头文件路径,这种全局设置方式非常有效。

优点:

  • 简单易用:只需一次调用,即可为所有目标设置头文件搜索路径。
  • 快速实现:适合快速搭建或验证简单项目。

缺点:

  • 全局性:一旦设置,后续所有的目标都会使用这些包含目录,难以做到细粒度的控制。这会增加项目规模和复杂性时的管理难度。
  • 可维护性差:如果项目变得复杂,全局的包含目录可能会导致不必要的依赖,或者由于头文件冲突而导致编译问题。
  • 潜在污染:多个模块共用一组全局的头文件路径,可能会引发意想不到的问题,如头文件覆盖或模块间的耦合度过高。

3. target_include_directories —— 精确控制每个目标的包含目录

为了克服 INCLUDE_DIRECTORIES 的全局性问题,CMake 引入了 target_include_directories 命令,它允许开发者为特定的目标设置包含目录。与 INCLUDE_DIRECTORIES 不同,这个命令具有更强的作用范围控制能力,并且支持三种不同的作用域:PRIVATEPUBLICINTERFACE,帮助管理目标之间的依赖关系。

语法:

target_include_directories(<target> [PRIVATE|PUBLIC|INTERFACE] <directories>)

  • PRIVATE:仅对当前目标可见,依赖于这个目标的其他目标不会继承这些包含目录。
  • PUBLIC:对当前目标和依赖于该目标的其他目标都可见。
  • INTERFACE:当前目标不会使用这些包含目录,但依赖于它的其他目标可以使用。

使用示例:

add_library(MyLibrary mylibrary.cpp) target_include_directories(MyLibrary PUBLIC ${CMAKE_SOURCE_DIR}/include PRIVATE ${CMAKE_SOURCE_DIR}/src )

在这个例子中,MyLibrary 会使用 includesrc 目录中的头文件:

  • PUBLICinclude 目录不仅会对 MyLibrary 可见,还会对依赖于 MyLibrary 的目标可见。
  • PRIVATEsrc 目录则仅对 MyLibrary 自己可见,外部目标不会继承这个路径。

适用场景:

  • 大型项目:在复杂的项目中,每个库或模块可能都有自己的依赖和头文件路径。这时,target_include_directories 能提供更加精细的控制。
  • 模块化开发:当项目采用模块化或库的方式进行构建时,每个模块的头文件路径通常是独立的。使用 target_include_directories 可以避免头文件路径之间的冲突,并且可以很好地管理库与库之间的依赖关系。
  • 公共和私有头文件区分:当一个库需要向外部暴露部分头文件(比如库的 API),但不希望暴露其内部实现的头文件时,可以利用 PUBLICPRIVATE 来进行管理。

优点:

  • 精确控制:每个目标可以独立管理自己的包含目录,减少不必要的全局污染。
  • 作用域管理:通过 PRIVATEPUBLICINTERFACE,可以更灵活地控制头文件路径的可见性,从而更好地管理模块间的依赖关系。
  • 可维护性强:在大型项目中,能够清晰地定义每个模块的头文件依赖,提升代码的可维护性。

缺点:

  • 语法复杂:相比 INCLUDE_DIRECTORIEStarget_include_directories 的语法和概念相对复杂,特别是对于新手来说,可能需要更多的学习时间。
  • 初期搭建繁琐:在项目早期搭建阶段,可能会觉得使用 target_include_directories 比较繁琐,因为需要为每个目标单独配置头文件路径。

4. INCLUDE_DIRECTORIEStarget_include_directories 的对比

特性INCLUDE_DIRECTORIEStarget_include_directories
作用范围全局仅影响指定目标
细粒度控制可以使用 PRIVATEPUBLICINTERFACE
适用项目小型项目,简单头文件依赖大型项目,复杂模块化开发
维护成本随着项目增大,维护难度增加清晰的依赖管理,维护性较好
推荐使用场景简单的构建流程精细的目标依赖管理

5. 最佳实践

  1. 优先使用 target_include_directories:在现代 CMake 项目中,尤其是模块化和大型项目,尽量使用 target_include_directories 来精确控制头文件的包含目录。它能提供更清晰的依赖关系管理,减少不必要的全局污染。

  2. 分清 PUBLICPRIVATEINTERFACE:合理使用这三者来管理库的头文件依赖。PUBLIC 适合对外暴露的 API 头文件,PRIVATE 用于内部实现细节,INTERFACE 则适合不直接使用但会传递依赖的情况。

  3. 减少全局依赖:避免滥用 INCLUDE_DIRECTORIES,尤其是在大型项目中,全局的头文件路径可能会引发意想不到的依赖和冲突问题。

  4. 模块化设计:当项目逐渐复杂化,考虑将项目划分为多个独立模块,每个模块只依赖于自己需要的头文件,使用 target_include_directories 来管理这些模块的头文件路径。


结论

在 CMake 中,INCLUDE_DIRECTORIEStarget_include_directories 都是管理头文件路径的重要工具,但它们适用于不同的场景。INCLUDE_DIRECTORIES 简单直观,但在大型项目中会变得难以维护。相反,target_include_directories 提供了更强大的控制能力,能够为每个目标精确地管理头文件路径。

在现代 CMake 项目中,推荐使用 target_include_directories,因为它能够更好地管理目标之间的依赖,并且有助于保持项目的清晰性和可维护性。

相关文章:

深入理解 CMake 中的 INCLUDE_DIRECTORIES 与 target_include_directories

在使用 CMake 构建系统时&#xff0c;指定头文件的包含路径是非常常见的一步。对于这个任务&#xff0c;CMake 提供了两种主要的命令&#xff1a;INCLUDE_DIRECTORIES 和 target_include_directories。虽然它们看似类似&#xff0c;但它们的作用范围、应用方式以及适用场景却有…...

【不知道原因的问题】java.lang.AbstractMethodError

项目场景&#xff1a; 提示&#xff1a;这里简述项目相关背景&#xff1a; 遇到了一个问题&#xff1a; java.lang.AbstractMethodError 问题描述 提示&#xff1a;这里描述项目中遇到的问题&#xff1a; 在Java开发中&#xff0c;java.lang.AbstractMethodError是一个常见…...

分布式篇(分布式事务)(持续更新迭代)

一、事务 1. 什么是事务 2. 事务目的 3. 事务的流程 4. 事务四大特性 原子性&#xff08;Atomicity&#xff09; 一致性&#xff08;Consistency&#xff09; 持久性&#xff08;Durability&#xff09; 隔离性&#xff08;Isolation&#xff09; 5. MySQL VS Oracle …...

[Linux] 逐层深入理解文件系统 (2)—— 文件重定向

标题&#xff1a;[Linux] 逐层深入理解文件系统 &#xff08;2&#xff09;—— 文件重定向 个人主页水墨不写bug &#xff08;图片来源于网络&#xff09; 目录 一、文件的读取和写入 二、文件重定向的本质 1.手动模拟重定向的过程——把标准输出重定向到redir.txt 2.重定向…...

html+css+js实现Badge 标记

实现效果&#xff1a; 代码实现&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Badge…...

纯css 轮播图片,鼠标移入暂停 移除继续

核心 滚动&#xff1a; animation: 动画名称 20s linear infinite normal;停止&#xff1a; animation: 动画名称 20s linear infinite paused; 完整例子&#xff1a; html: <div class"carousel-wrapper"><div class"carousel"><div cl…...

iOS GCD的基本使用

一:什么是GCD GCD的全程是:Grand Central Dispatch, 直白的用汉语翻译就是:厉害的中枢调度器. GCD 是iOS 的多线程技术的实现方案,但是它并不是多线程技术,它是“并发解决技术”,是苹果公司研发的,会自动管理线程(这一段定义有点拗口,简单了解就行) GCD会自动管理线程的生命…...

如何设计开发RTSP直播播放器?

技术背景 我们在对接RTSP直播播放器相关技术诉求的时候&#xff0c;好多开发者&#xff0c;除了选用成熟的RTSP播放器外&#xff0c;还想知其然知其所以然&#xff0c;对RTSP播放器的整体开发有个基础的了解&#xff0c;方便方案之作和技术延伸。本文抛砖引玉&#xff0c;做个…...

Java基础系列-一文搞懂自定义排序

java自定义排序 自定义排序的理解&#xff1a; 我们首先看需求&#xff1a;一个二维数组 [[1,3],[8,10],[15,18],[2,6]] 我们的需求是根据集合&#xff08;二维数组取出来的数据&#xff09; 左边小的左边这种方式排序 例如1<8 排序方式就是[1,3],[8,10] 此时我们就需…...

扫普通链接二维码打开小程序

1. 2.新增规则&#xff08;注意下载文件到跟目录下&#xff0c;需要建个文件夹放下载的校验文件&#xff09; 3.发布 ps&#xff1a;发布后&#xff0c;只能访问正式版本。体验版本如果加了 测试链接http://xxx/xsc/10 那么http://xxx/xsc/aa.....应该都能访问 例如aa101 aa…...

计算机储存与分区

Disk partitioning 盘分区是在辅助储存上创建一个或多个区域&#xff0c;以便可以单独管理每个区域。而这些区域称为分区&#xff08;partition&#xff09;。这通常是在为新盘选择分区方案后&#xff0c;需要做的事。 MBR and GPT 分区方案&#xff08;分区表&#xff09;有…...

OpenCV之换脸技术:一场面部识别的奇妙之旅

在这个数字化与智能化并进的时代&#xff0c;图像处理技术日益成为连接现实与虚拟世界的桥梁。其中&#xff0c;换脸技术作为一项颇受欢迎且富有挑战性的应用&#xff0c;不仅让人惊叹于技术的魔力&#xff0c;更在娱乐、影视制作等领域展现了无限可能。今天&#xff0c;我们就…...

Linux学习笔记9 文件系统的基础

一、查看文件组织结构 Linux中一切都是文件。 Linux和Win的文件系统不是一个结构&#xff0c;Linux存在的根目录是所有目录的起点。 所有的存储空间和设备共享一个根目录&#xff0c;不同的磁盘块和分区挂载在其下&#xff0c;成为某个子目录的子目录&#xff0c;甚至设备也挂…...

Android OpenGL粒子特效

在本篇&#xff0c;我们将开启一个新的项目&#xff0c;探索粒子的世界。粒子是一种基本的图形元素&#xff0c;它们通常被表示为一组点。通过巧妙地组合一些基础的物理效果&#xff0c;我们能够创造出许多令人惊叹的视觉效果。想象一下&#xff0c;我们可以模拟一个水滴从喷泉…...

5 -《本地部署开源大模型》在Ubuntu 22.04系统下ChatGLM3-6B高效微调实战

在Ubuntu 22.04系统下ChatGLM3-6B高效微调实战 无论是在单机单卡&#xff08;一台机器上只有一块GPU&#xff09;还是单机多卡&#xff08;一台机器上有多块GPU&#xff09;的硬件配置上启动ChatGLM3-6B模型&#xff0c;其前置环境配置和项目文件是相同的。如果大家对配置过程还…...

dpkg:错误:另外一个进程已经为dpkg前端锁加锁

一、 问题描述 在新装ubuntu系统时&#xff0c;我们常常会遇见dpkg的错误&#xff0c;dpkg:错误:另外一个进程已经为dpkg前端锁加锁&#xff0c;如下图。 二、问题解决 方法一 先执行sudo rm /var/lib/dpkg/lock-frontend然后再继续安装软件包&#xff0c;如果出现问题dpkg:…...

基于SSM服装定制系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;服装类型管理&#xff0c;服装信息管理&#xff0c;服装定制管理&#xff0c;留言反馈&#xff0c;系统管理 前台账号功能包括&#xff1a;系统首页&#xff0c;个人中心&#xf…...

RK3588开发笔记-usb3.0 xhci-hcd控制器挂死问题解决

目录 前言 一、问题现象 二、问题分析 三、问题排查 总结 前言 在使用 RK3588 芯片进行开发的过程中,我遇到了 USB 3.0 xHCI-HCD 控制器外接5G通讯模块偶尔挂死的问题。这个问题导致 USB 设备失去响应,且不能恢复,需要重启整个系统才能恢复使用,针对该问题进行大量测试以…...

深入解析TCP/IP协议:网络通信的基石

1. 引言 TCP/IP 协议是现代计算机网络的核心&#xff0c;它为互联网上的设备提供了通信的基础。在网络通信中&#xff0c;TCP/IP 协议栈是无处不在的&#xff0c;无论是个人设备的浏览器请求&#xff0c;还是大型分布式系统的内部通信&#xff0c;都依赖于它的稳定、高效与可靠…...

基于微信小程序的汽车预约维修系统(lw+演示+源码+运行)

基于微信小程序的汽车预约维修系统 摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了基于微信小程序的汽车预约维修系统的开发全过程。通过分析基于微信小程序的汽车预约维修系统管理的不足&#xff0c;创建了…...

网络六边形受到攻击

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 抽象 现代智能交通系统 &#xff08;ITS&#xff09; 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 &#xff08;…...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

条件运算符

C中的三目运算符&#xff08;也称条件运算符&#xff0c;英文&#xff1a;ternary operator&#xff09;是一种简洁的条件选择语句&#xff0c;语法如下&#xff1a; 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true&#xff0c;则整个表达式的结果为“表达式1”…...

图表类系列各种样式PPT模版分享

图标图表系列PPT模版&#xff0c;柱状图PPT模版&#xff0c;线状图PPT模版&#xff0c;折线图PPT模版&#xff0c;饼状图PPT模版&#xff0c;雷达图PPT模版&#xff0c;树状图PPT模版 图表类系列各种样式PPT模版分享&#xff1a;图表系列PPT模板https://pan.quark.cn/s/20d40aa…...

Mac下Android Studio扫描根目录卡死问题记录

环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中&#xff0c;提示一个依赖外部头文件的cpp源文件需要同步&#xff0c;点…...

return this;返回的是谁

一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请&#xff0c;不同级别的经理有不同的审批权限&#xff1a; // 抽象处理者&#xff1a;审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...

Java数值运算常见陷阱与规避方法

整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...

Linux中《基础IO》详细介绍

目录 理解"文件"狭义理解广义理解文件操作的归类认知系统角度文件类别 回顾C文件接口打开文件写文件读文件稍作修改&#xff0c;实现简单cat命令 输出信息到显示器&#xff0c;你有哪些方法stdin & stdout & stderr打开文件的方式 系统⽂件I/O⼀种传递标志位…...

Python网页自动化Selenium中文文档

1. 安装 1.1. 安装 Selenium Python bindings 提供了一个简单的API&#xff0c;让你使用Selenium WebDriver来编写功能/校验测试。 通过Selenium Python的API&#xff0c;你可以非常直观的使用Selenium WebDriver的所有功能。 Selenium Python bindings 使用非常简洁方便的A…...

渗透实战PortSwigger Labs指南:自定义标签XSS和SVG XSS利用

阻止除自定义标签之外的所有标签 先输入一些标签测试&#xff0c;说是全部标签都被禁了 除了自定义的 自定义<my-tag onmouseoveralert(xss)> <my-tag idx onfocusalert(document.cookie) tabindex1> onfocus 当元素获得焦点时&#xff08;如通过点击或键盘导航&…...