IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> CMake include_directories 和 target_include_directories,头文件的搜索顺序 -> 正文阅读

[C++知识库]CMake include_directories 和 target_include_directories,头文件的搜索顺序

业务中遇到个问题,引用了 jsoncpp 这个库之后,需要引用其头文件,但其头文件进一步引用了 jsoncpp 安装位置的其他头文件,但如果一台 Linux 机器上在不同的路径安装了两个不同版本的 jsoncpp 库,并且这两个路径都是该项目的头文件包含路径,那么,编译器会先找哪个路径下的头文件呢?带着这个问题,我开始翻阅 camke 的官方文档,由于是全英文版,读起来还是很费劲,因此先翻译出来。
翻译完之后发现,include 的顺序跟翻译关系不大,因此,又将文档翻译写到了后半段,而把实验写到了前半段。

头文件搜索顺序

先说结论,编译器会按照 CMake 脚本给出的 include 路径顺序从头到尾(从左往右)依次搜索,如果在前面找到了相应的头文件,则不再去后面搜索。

实验

目录结构

在这里插入图片描述

文件内容

// include1/includea.h
int i = 1;
// include2/includea.h
int i = 2;
// src/src.cpp
#include "includea.h"
#include <iostream>
using namespace std;
int main() {
	cout << "Hello, " << a << endl;
}
cmake_minimum_required(VERSION 3.10.0)
project(includeorder)
aux_source_directory(${PROJECT_SOURCE_DIR}/src SRC)
add_executable(${PROJECT_NAME} ${SRC})
target_include_directories(${PROJECT_NAME} PRIVATE ${PROJECT_SOURCE_DIR}/include2 ${PROJECT_SOURCE_DIR}/include1)

编译后执行结果:Hello, 2

cmake_minimum_required(VERSION 3.10.0)
project(includeorder)
aux_source_directory(${PROJECT_SOURCE_DIR}/src SRC)
add_executable(${PROJECT_NAME} ${SRC})
target_include_directories(${PROJECT_NAME} PRIVATE ${PROJECT_SOURCE_DIR}/include1 ${PROJECT_SOURCE_DIR}/include2)

编译后执行结果:Hello, 1

文档翻译

include_directories

添加包含路径到构建任务。
include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 ...]
给编译器添加给出的路径,用来搜索包含文件。相对路径将被翻译成相对于当前脚本所在目录的相对路径。
这些包含目录将被添加到当前 CMakeLists 文件的 INCLUDE_DIRECTORIES 目录属性中。他们同时也会被添加到当前 CMakeLists 文件中的每一个构建目标的目标属性中。目标属性的值是被生成器使用的。
这些路径会被默认添加到当前的包含路径列表的尾部,这种默认行为也可以通过修改参数 CMAKE_INCLUDE_DIRECTORIES_BEFOREON 来修改。显式使用 AFTERBEFORE,你可以选择添加到包含列表的头部或者尾部,与默认行为无关。
如果使用 SYSTEM 参数,在某些平台上将会告知编译器这些路径是系统包含路径。使用该参数可以实现一些效果,例如让编译器跳过警告,或者那些固定安装的系统文件不会被认为是依赖项——参考编译器文档。
include_directories 的参数也可以借助语法 “$<…>” 使用 “生成器表达式”,参考 cmake-generator-expressions(7)指南来获取可用表达式。参考 cmake-buildsystem(7) 指南来获取关于定义构建系统属性的更多知识。
**注意:**建议使用 target_include_directores() 指令给单独的构建目标添加包含目录,并可选地传播(propagate)或导出他们给相关依赖(dependents)。

target_include_directories

给构建目标添加包函目录。

target_include_directories(<target> [system] [AFTER|BEFORE]
							<INTERFACE|PUBLIC|PRIVATE> [items1...]
							[<INTERFACE|PUBLIC|PRIVATE> [items2...]...])

针对给定的构建目标(target)定义编译时使用的包含路径。参数 <target> 必须是已被类似于 add_executable() 或者 add_library() 命令创建出来的,并且不能是一个 ALIAS TARGET
明确使用参数AFTERBEFORE,你可以选择添加到尾部或者头部,不受默认行为影响。
参数 INTERFACEPUBLICPRIVATE 被用来指定接下来的参数的作用范围。
PRIVATEPUBLIC 会将 INCLUDE_DIRECOTRIES 属性添加给目标 <target>
PUBLICINTERFACE 参数会将 INTERFACE_INCLUDE_DIRECTORIES 属性添加给目标 <target>
关于 INCLUDE_DIRECTORIESINTERFACE_INCLUDE_DIRECTORIES 的差异请点击链接。
接下来的参数定义了包含目录。
3.11 版本的新功能:允许设置 INTERFACE 参数来影响 导入的目标.
对同一目标重复调用命令将添加按调用顺序相关参数到列表尾部。
在某些平台,使用 SYSTEM 参数可告知编译器这些目录是系统包含目录,这会让编译器忽略警告或者跳过包含相关头文件。此外,系统包含目录会在普通包含目录之后被搜索,无论在列表中的顺序如何。
如果 SYSTEM 参数和 PUBLIC 参数或者 INTERFACE 参数同时使用,这些包含目录会被添加到INTERFACE_SYSTEM_INCLUDE_DIRECTORIES 目标属性。
给到 target_include_directories 的参数可以是使用 $<...> 语法的生成器表达式。参考 cmake-generator-expressions(7)指南来获取可用表达式。参考 cmake-buildsystem(7) 指南来获取关于定义构建系统属性的更多知识。
定义的包含目录可以使绝对路径或相对路径,相对路径将被翻译为相对于当前脚本所在目录(CMAKE_CURRENT_SOURCE_DIR)的路径,转换成一个绝对路径存储在在相关目标属性中。如果路径是以生成器表达式开头的,该路径将被认为是一个绝对路径(有一个例外,下面注明),并且不做任何修改地使用。
以下内容由于跟主题关系不大。不再翻译,暂时贴上原文,有空再翻。
Include directories usage requirements commonly differ between the build-tree and the install-tree. The BUILD_INTERFACE and INSTALL_INTERFACE generator expressions can be used to describe separate usage requirements based on the usage location. Relative paths are allowed within the INSTALL_INTERFACE expression and are interpreted as relative to the installation prefix. Relative paths should not be used in BUILD_INTERFACE expressions because they will not be converted to absolute. For example

target_include_directories(mylib PUBLIC
  $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/mylib>
  $<INSTALL_INTERFACE:include/mylib>  # <prefix>/include/mylib
)
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-05-12 16:18:51  更:2022-05-12 16:19:07 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 19:09:25-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码