深入理解 CMake 中的 INCLUDE_DIRECTORIES 与 target_include_directories

news2024/10/19 15:19:59

在使用 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,因为它能够更好地管理目标之间的依赖,并且有助于保持项目的清晰性和可维护性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2218563.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

flutter实现头像覆盖轮播滚动组件

效果如下: 支持自定义图片大小 支持设置覆盖比例 支持设置最大展示数量 支持设置缩放动画比例 支持自定义动画时长、以及动画延迟时长 支持当图片List长度小于或者登录设置的最大展示数量时禁用滚动动画。 import ../../library.dart;class CircularImageList extends Sta…

2024全网最详细CTF入门指南、CTF夺旗赛使用工具及刷题网站

2024年最新的CTF&#xff08;Capture The Flag&#xff0c;夺旗赛&#xff09;入门指南如下&#xff0c;涵盖了入门思路、常见题型及练习网站推荐&#xff0c;帮助你逐步了解并提升在CTF中的解题技巧。 如果你对网络安全入门感兴趣&#xff0c;我给大家整理好了相关资料&#…

基于SpringBoot+Vue的蜗牛兼职网的设计与实现(带文档)

基于SpringBootVue的蜗牛兼职网的设计与实现&#xff08;带文档) 开发语言:Java数据库:MySQL技术:SpringBootMyBatisVue等工具:IDEA/Ecilpse、Navicat、Maven 该系统主要分为三个角色&#xff1a;管理员、用户和企业&#xff0c;每个角色都有其独特的功能模块&#xff0c;以满…

【从零到一的笔试突破】——day1笔试巅峰(6道笔试题)ACM模式让笔试更有感觉

文章目录 数字统计&#xff08;数学模拟&#xff09;两个数组的交集&#xff08;哈希&#xff09;点击消除&#xff08;栈&#xff09;牛牛的快递&#xff08;模拟&#xff09;最小花费爬楼梯&#xff08;动态规划&#xff09;数组中两个字符串的最小距离&#xff08;滑动窗口o…

智慧社区Web平台:Spring Boot技术实现

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常…

SQL进阶技巧:如何使数组中的固定参数动态化? | SQL中的滑动窗口如何实现?

目录 0 场景描述 1 数据准备 2 实现思路 问题2&#xff1a;如何动态获取年份&#xff0c;年份能够自动更新&#xff1f; 3 小结 如果觉得本文对你有帮助&#xff0c;想进一步学习SQL语言这门艺术的&#xff0c;那么不妨也可以选择去看看我的博客专栏 &#xff0c;部分内…

【高频SQL基础50题】46-50

SQL时刻。 目录 1.至少有5名直接下属的经理 2.确认率 3.游戏玩法分析 IV 4.部门工资前三高的所有员工 5.查找拥有有效邮箱的用户 1.至少有5名直接下属的经理 子查询。 1.先找出至少有5名直接下属的经理号managerId 2.根据经理号找到对应名字 # Write your MySQL query…

【unity小技巧】unity C#对DateTime的常见操作,用于处理日期和时间

在Unity中&#xff0c;DateTime 是一个非常有用的结构&#xff0c;用于处理日期和时间。以下是一些常见的 DateTime 操作示例&#xff1a; 1. 获取当前时间 DateTime now DateTime.Now;2. 创建特定日期和时间 DateTime specificDate new DateTime(2023, 10, 15, 14, 30, 0…

电力交易员职业标准-----达到基本入行标准(四级/中级)题库-----职业鉴定理论篇-----单选题目6~题目10-----持续更新

电力交易员职业标准-----达到基本入行标准&#xff08;四级/中级&#xff09;题库-----职业鉴定理论篇-----主目录-----持续更新https://blog.csdn.net/grd_java/article/details/143033828 2024 年电力交易员(中级工)职业鉴定理论考试题库 注意&#xff1a;每道题下面都会放相…

深度学习-机器学习与传统编程区别

在当今数字化时代&#xff0c;机器学习成为了技术领域的热门话题。本文将介绍机器学习与传统编程的不同之处&#xff0c;以及机器学习在解决复杂问题和实现智能化的巨大潜力&#xff0c;从处理方式、开发过程、驱动方式、技术要求和应用场景等5个方面进行介绍。 1、处理方式 机…

高效计算!|海鸥优化算法SOA理论与实现(Matlab/Python双语言教程)

文章来源于我的个人公众号&#xff1a;KAU的云实验台&#xff0c;主要更新智能优化算法的原理、应用、改进 MATLAB、PYTHON 海鸥是自然界中最常见的一类海鸟&#xff0c;主要以群居的生存方式遍布在各大海港、湖泊、河流地区。它们拥有较高的群集智慧&#xff0c;每到冬季&a…

冲锋衣市场洞察:全方位数据分析与趋势展望

冲锋衣整体数据分析 一. 概述 本报告基于从淘宝商品搜索接口和淘宝精确月销量接口中提取的数据&#xff0c;分析了前百个品牌在销售额上的占比情况。分析涵盖了销售额和占比的数据&#xff0c;为决策提供了依据。&#xff08;数据获取时间&#xff1a;2024.10.08&#xff09;…

数据分析方法(回归分析,决策树与神经网络,提升树,时间序列分析,假设检验,用户画像,竞品分析)等

1.回归分析 回归分析是一种统计方法&#xff0c;用于探索自变量&#xff08;预测变量&#xff09;和因变量&#xff08;目标变量&#xff09;之间的关系。它可以帮助预测变量的变化对目标变量的影响大小。例如&#xff0c;简单线性回归用于分析两个变量之间的线性关系&#xf…

快速创建一个vue项目并运行

前期准备工作: 1.安装node 2.安装npm 3.设置淘宝镜像 4.全局安装webpack 5.webpack 4.X 开始&#xff0c;需要安装 webpack-cli 依赖 6.全局安装vue-cli 正文开始: 1.创建项目 ,回车 vue init webpack vue-svg > Project name vue-demo 项目名称 回车 > Pro…

84.【C语言】数据结构之顺序表的头部插入和删除

目录 3.操作顺序表 1.分析头部插入函数 SeqList.c写入 容量检查函数 注意 main.c改为 SeqList.h添加SLPushFront的声明 运行结果 2.分析头部删除函数 SLPopFront代码 main.c改为 SeqList.h添加SLPopFront的声明 图分析 运行结果 承接83.【C语言】数据结构之顺序表…

文心一言 VS 讯飞星火 VS chatgpt (372)-- 算法导论24.4 4题

四、请将单源单目的地最短路径问题表示为一个线性规划问题。如果要写代码&#xff0c;请用go语言。 文心一言&#xff1a; 单源单目的地最短路径问题可以通过线性规划&#xff08;Linear Programming, LP&#xff09;进行建模。假设我们有一个加权有向图 $ G (V, E) $&#…

【LeetCode】每日一题 2024_10_14 鸡蛋掉落(记忆化搜索)

前言 每天和你一起刷 LeetCode 每日一题~ LeetCode 启动&#xff01; 题目&#xff1a;鸡蛋掉落 代码与解题思路 今天的题目是昨天的进阶版&#xff0c;昨天给了 2 个鸡蛋&#xff0c;让我们求在一栋有 n 层楼的建筑中扔鸡蛋的最大操作次数 但是今天的题目给了 k 个鸡蛋&am…

linux 离线安装redis

1.官网下载 https://redis.io/download 或者去github下载 2.安装 Redis 解压 unzip redis-6.2.16.zip安装gcc #由于 redis 是用 C 语言开发&#xff0c;安装之前必先确认是否安装 gcc 环境&#xff08;gcc -v&#xff09; gcc -v若无安装gcc&#xff0c;参考我的文章 Lin…

kaggle中如何更新上传自定义的数据集dataset?

前言: kaggle notebook中可以上传自己的数据集进行训练&#xff0c;但是如果我们发现这个数据集有一部分需要更新下呢&#xff0c;这时候我们不必新建一个数据集&#xff0c;直接在原来的版本上进行更新即可。 以datasett的更新为例&#xff0c;在这个界面是看不到更新按钮的 …

Axure使用echarts详细教程

本次使用的axure版本为rp9,下面是效果图。 接下来是详细步骤 【步骤1】在axure上拖一个矩形进来&#xff0c;命名为myChart(这个根据实际情况来,和后面的代码对应就好) 【步骤2】 点击交互->选择加载时->选择打开链接->链接外部地址 点击fx这个符号 【步骤3】在弹…