windows--cmake与c++的使用教程(14)

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 一个例子说明

  • 目录结构:
Copy Highlighter-hljs
│ 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
Copy Highlighter-hljs
# 指定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之前,增加下一脚本
Copy Highlighter-hljs
# 参数为: 当前脚本目录/include目录所在绝对路径 include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
  • 此时,CMakeLists.txt完整脚本为
Copy Highlighter-hljs
# 指定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 )
  • 执行项目编译, 可见编译结果为通过:
Copy Highlighter-hljs
[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#

  • 需要为 每个 项目设置头文件搜寻路径设置
Copy Highlighter-hljs
# 为每个项目指定头文件搜索路径 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脚本
Copy Highlighter-hljs
# 指定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)
  • 编译项目,通过。
Copy Highlighter-hljs
[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的项目。
  • 目录
Copy Highlighter-hljs
. │ CMakeLists.txt │ ├─Common │ CommonOutput.cmake │ ├─demo │ CMakeLists.txtmain.cc │ ├─include │ Typedef.h │ └─src main.cc
  • 其中,demo目录下CMake脚本内容仅仅为
Copy Highlighter-hljs
cmake_minimum_required(VERSION 3.18) # 指定项目 project(ProjectDemo) # ------------------------------------------- # 项目A add_executable(ProjectDemo ${CMAKE_CURRENT_SOURCE_DIR}/main.cc )
  • 而demo目录下的main.cc中的代码 没有 引用 顶层目录/include 目录下的任何文件
Copy Highlighter-hljs
#include <iostream> int main(int argc, char*argv[]) { std::cout << "hello" << std::endl; return 0; }
  • 回到顶层的CMakeLists.txt中,代码略微的不一样, 增加 add_subdirectory(demo) 用于创建子项目。
Copy Highlighter-hljs
# 指定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 达到范围使用最小化原则,避免一些不必要的麻烦。
posted @   mohist  阅读(1078)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示
CONTENTS