1 概述

本节目标:target_include_directories 用法

2 作用

  • target_include_directories 的作用, 用于给固定目标指定头文件搜索路径。
  • modern cmake之前,与之对应的是 include_directoriesinclude_directories也是用于设置头文件搜索路径。
  • 它俩对比
名称 区别
target_include_directories 为指定的目标设置头文件搜索路径设置
include_directories 为当前CMakeLists.txt中的项目设定头文件搜索路径设置
  • 也就是说,CMakeLists.txt脚本中,可创建多个项目
    • 当使用target_include_directories时,只能为某一个项目设置头文件设置
    • 当使用include_directories时,当前脚本文件中的所有项目都会使用include_directories参数中的路径。 具有传递性(下面说)

3 一个例子说明

  • 目录结构:
│  CMakeLists.txt
│  
├─Common
│      CommonOutput.cmake
│      
├─include
│      Typedef.h
│      
└─src
        main.cc
  • 有这样一个 CMakeLists.txt 脚本文件, 当前脚本中创建了项目A、B和C, 而这三个项目中,main.cc 又需要 ${CMAKE_CURRENT_SOURCE_DIR}/include 目录下的头文件typedef.h
# 指定CMake脚本解析的最低版本,
cmake_minimum_required(VERSION 3.18)

# 指定项目
project(HelloCMake)

# 引入脚本:参数为脚本文件的全路径
include(${CMAKE_CURRENT_SOURCE_DIR}/Common/CommonOutput.cmake)

# -------------------------------------------
# 项目A
add_executable(ProjectA 
${CMAKE_CURRENT_SOURCE_DIR}/src/main.cc 
${CMAKE_CURRENT_SOURCE_DIR}/include/typedef.h   
)

# -------------------------------------------
# 项目B
add_executable(ProjectB
${CMAKE_CURRENT_SOURCE_DIR}/src/main.cc 
${CMAKE_CURRENT_SOURCE_DIR}/include/typedef.h  


# -------------------------------------------
# 项目C
add_executable(ProjectC
${CMAKE_CURRENT_SOURCE_DIR}/src/main.cc 
${CMAKE_CURRENT_SOURCE_DIR}/include/typedef.h 
)

上面这段脚本构建没有问题。不过项目编译却无法通过编译, 因为没有指定typedef.h文件的搜索路径。

3.1 如果通过项目编译?

  • 设置项目的头文件搜索路径, 下面是解决方法

3.2 使用include_directories

  • include_directories用法简单,括号内写路径即可。
  • 创建项目A之前,增加下一脚本
# 参数为: 当前脚本目录/include目录所在绝对路径
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
  • 此时,CMakeLists.txt完整脚本为
# 指定CMake脚本解析的最低版本,
cmake_minimum_required(VERSION 3.18)

# 指定项目
project(HelloCMake)


# 引入脚本:参数为脚本文件的全路径
include(${CMAKE_CURRENT_SOURCE_DIR}/Common/CommonOutput.cmake)

# 参数为: 当前脚本目录/include目录所在绝对路径
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)

# -------------------------------------------
# 项目A
add_executable(ProjectA 
${CMAKE_CURRENT_SOURCE_DIR}/src/main.cc 
${CMAKE_CURRENT_SOURCE_DIR}/include/typedef.h   
)

# -------------------------------------------
# 项目B
add_executable(ProjectB
${CMAKE_CURRENT_SOURCE_DIR}/src/main.cc 
${CMAKE_CURRENT_SOURCE_DIR}/include/typedef.h  
)


# -------------------------------------------
# 项目C
add_executable(ProjectC
${CMAKE_CURRENT_SOURCE_DIR}/src/main.cc 
${CMAKE_CURRENT_SOURCE_DIR}/include/typedef.h 
)
  • 执行项目编译, 可见编译结果为通过:
[build]   ProjectC.vcxproj -> C:\A\publish\x64\bin\debug64\ProjectC.exe
[build]   ProjectB.vcxproj -> C:\A\publish\x64\bin\debug64\ProjectB.exe
[build]   ProjectA.vcxproj -> C:\A\publish\x64\bin\debug64\ProjectA.exe

3.3 使用target_include_directories

  • 需要为 每个 项目设置头文件搜寻路径设置
# 为每个项目指定头文件搜索路径
target_include_directories( ProjectA PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
target_include_directories( ProjectB PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
target_include_directories( ProjectC PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
  • 此时完整CmakeLists.txt脚本
# 指定CMake脚本解析的最低版本,
cmake_minimum_required(VERSION 3.18)

# 指定项目
project(HelloCMake)


# 引入脚本:参数为脚本文件的全路径
include(${CMAKE_CURRENT_SOURCE_DIR}/Common/CommonOutput.cmake)

# -------------------------------------------
# 项目A
add_executable(ProjectA 
${CMAKE_CURRENT_SOURCE_DIR}/src/main.cc 
${CMAKE_CURRENT_SOURCE_DIR}/include/typedef.h   
)

# -------------------------------------------
# 项目B
add_executable(ProjectB
${CMAKE_CURRENT_SOURCE_DIR}/src/main.cc 
${CMAKE_CURRENT_SOURCE_DIR}/include/typedef.h  
)


# -------------------------------------------
# 项目C
add_executable(ProjectC
${CMAKE_CURRENT_SOURCE_DIR}/src/main.cc 
${CMAKE_CURRENT_SOURCE_DIR}/include/typedef.h 
)

# 为每个项目指定头文件搜索路径
target_include_directories( ProjectA PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
target_include_directories( ProjectB PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
target_include_directories( ProjectC PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
  • 编译项目,通过。
[build]   ProjectB.vcxproj -> C:\A\publish\x64\bin\debug64\ProjectB.exe
[build]   ProjectA.vcxproj -> C:\A\publish\x64\bin\debug64\ProjectA.exe
[build]   ProjectC.vcxproj -> C:\A\publish\x64\bin\debug64\ProjectC.exe

5 使用注意

  • 如果你的CMakeLists.txt脚本中只有单个项目, 那么, target_include_directoriesinclude_directories的效果是一样的
  • 如果CMakeLists.txt脚本中存在多个项目,建议使用target_include_directories,避免 某些项目引用到其他用不到的目录而引发的问题。
  • Modern CMake中 支持 target_include_directories 用法。
  • 简明扼要
    • include_directories: 1 VS 多
    • target_include_directories: 1 VS 1

5.1 include_directories具有传递性

  • 什么意思呢? include_directories 为会 子目录中的项目增加头文件路径的设置。
  • 还是上面的那个目录结构,此时多了一个文件夹demo, demo目录下也有一个CMakeLists.txt脚本,demo目录下CMakeLists.txt脚本中创建了一个名为 ProjectDemo的项目。
  • 目录
.
│  CMakeLists.txt
│      
├─Common
│      CommonOutput.cmake
│      
├─demo
│      CMakeLists.txt
│      main.cc
│      
├─include
│      Typedef.h
│      
└─src
        main.cc
  • 其中,demo目录下CMake脚本内容仅仅为
cmake_minimum_required(VERSION 3.18)

# 指定项目
project(ProjectDemo)

# -------------------------------------------
# 项目A
add_executable(ProjectDemo
${CMAKE_CURRENT_SOURCE_DIR}/main.cc
)
  • 而demo目录下的main.cc中的代码 没有 引用 顶层目录/include 目录下的任何文件
#include <iostream>

int main(int argc, char*argv[])
{
    std::cout << "hello" << std::endl;
    return 0;
}
  • 回到顶层的CMakeLists.txt中,代码略微的不一样, 增加 add_subdirectory(demo) 用于创建子项目。
# 指定CMake脚本解析的最低版本,
cmake_minimum_required(VERSION 3.18)

# 指定项目
project(HelloCMake)


# 引入脚本:参数为脚本文件的全路径
include(${CMAKE_CURRENT_SOURCE_DIR}/Common/CommonOutput.cmake)

# 引入头文件
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)

# -------------------------------------------
# 项目A
add_executable(ProjectA 
${CMAKE_CURRENT_SOURCE_DIR}/src/main.cc 
${CMAKE_CURRENT_SOURCE_DIR}/include/typedef.h   
)

# 子项目 Demo
add_subdirectory(demo)

请允许我再总结下: ProjectDemo没有引用 typedef.h文件。 ProjectA项目引用了 Typedef.h文件。 typedef.h位于顶层CMakeLists.txt文件所在目录/include目录下

  • 5.2 构建, 查看传递性
  • 构建 [5.1] 中的脚本,使用VS2019打开,查看 ProjectDemo项目属性:
  • ProjectDemo 明明没有引用,而项目设置中却出现了 对目录的引用设置。
  • 这就是 include_directories 的传递性。使用需要注意

6 target_include_directories 使用

  • target_include_directories 的作用是为具体的目标设置 INCLUDE_DIRECTORIESINTERFACE_INCLUDE_DIRECTORIES 属性。
  • PRIVATEPUBLIC 关键字是用来设定目标的 INCLUDE_DIRECTORIES属性
  • INTERFACEPUBLIC 关键字是用来设定目标的 INTERFACE_INCLUDE_DIRECTORIES属性
  • 区别:
    • PRIVATE: 仅当前目标使用,不会将 PRIVATE后 紧跟的参数进行传递
    • PUBLIC: PUBLIC 后面紧跟的参数, 自己使用外, 也传递给给别人使用
    • INTERFACE: INTERFACE 后面紧跟的参数,自己不用,传递给别人使用

这三个关键字都是用来限定 其后紧跟的参数的范围。 可见: PUBLIC 就是 PRIVATE 和 INTERFACE 两者的结合 。

7 我的使用经验

  • 模块或者项目内,尽量使用 PRIVATE 达到范围使用最小化原则,避免一些不必要的麻烦。

原文地址:http://www.cnblogs.com/pandamohist/p/16920528.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性