windows--cmake与c++的使用教程(11)
1 概述
- 本文基于前文环境
本节目标:设置项目包含头文件路径, 关键语法target_include_directories。
2 目标
- main.cc 与 Typedef.h不在同一个目录下, Typedef.h 位于include目录下,main.cc位于src目录下
- main.cc 使用TypeDef.h中定义的类型和函数
2.1 目录结构
- 目录结构
.
│ CMakeLists.txt
│
├─Common
│ CommonOutput.cmake
│
├─include
│ Typedef.h
│
└─src
main.cc
2.2 main.cc代码
- 使用头文件 Typedef.h 中的函数 engine_count 和 结构体stAir
#include <iostream>
#include <Typedef.h>
/// 调用飞机属性
void call_air_demo()
{
// 结构体使用范例
cmake_demo::stAir aircraft(5678, std::string("B-0001"));
// 输出
std::cout << "\nid=" << aircraft.id_ << ", name=" << aircraft.name_.c_str() << "\n";
// 函数使用范例
std::cout << "engine_count=" << cmake_demo::air_engine_count() << "\n";
}
/// 程序入口
int main(int argc, char* argv[], char* env[])
{
call_air_demo();
return 0;
}
2.3 Typedef.h代码
- 定义函数engine_count 和 结构体 stAir
- 上码:
#ifndef TYPE_DEF_H_
#define TYPE_DEF_H_
#include <string>
namespace cmake_demo
{
//----------------------------------------------------------------
// 飞机引擎数量
//----------------------------------------------------------------
int air_engine_count()
{
return 4;
}
///----------------------------------------------------------------
/// 定义飞机属性
///----------------------------------------------------------------
struct stAir_
{
public:
stAir_(const int & id, const std::string& newName)
{
id_ = id;
name_ = newName;
}
public:
/// 飞机ID
int id_;
/// 唯一飞机机号
std::string name_;
};
using stAir = stAir_;
} // namespace
#endif /// ! TYPE_DEF_H_
3 编写CMake脚本
3.1 头文件加入项目
- 项目因为使用到了 typedef.h 文件, 所以, 也需要将其纳入项目中
3.2 指定项目搜索头文件路径 target_include_directories
- 主角: target_include_directories
- 具体用法可参考官方文档。 这里仅仅演示自己够用的语法
- target_include_directories使用时,需要指定 目标 和 路径 以及 属性传递(这里,不展开,以后专门出一随笔说明) (属性传递有3个: PRIVATE, PUBLIC 和 INTERFACE)
- target_include_directories 使用时, 一次调用,可以指定多个路径, 比如
target_include_directories( ${PROJECT_NAME}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include # 路径1
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src # 路径2
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} # 路径3
)
- 上面的代码也可以写成:
target_include_directories( ${PROJECT_NAME}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include # 路径1
${CMAKE_CURRENT_SOURCE_DIR}/src # 路径2, 少了关键字 PRIVATE
${CMAKE_CURRENT_SOURCE_DIR} # 路径3, 少了关键字 PRIVATE
)
- target_include_directories本文演示中的例子
# 指定 ${PROJECT_NAME}, 也就是 HelloCMake 的头文件搜索路径
target_include_directories( ${PROJECT_NAME} # 参数1 项目名称
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include # 参数2, 指定哪个搜索头文件路径, 这里的PRIVATE是cmake内置系统关键字,这里不展开,后面专门出一期随笔说清楚
)
target_include_directories 作用
target_include_directories 作用
target_include_directories 作用
- target_include_directories 用于解决代码中使用 #include<头文件> ,编译器无法找到头文件的问题。它的作用就是告诉编译器,应该去哪个目录下搜索头文件
- 本文范例中的例子,告诉编译器, 编译HelloCmake时, 应该去${CMAKE_CURRENT_SOURCE_DIR}/include目录下找 头文件Typedef.h
target_include_directories 使用顺序
- 使用 target_include_directories 需要创建项目后再使用,也就是位于 add_library和 add_executable之后使用,否则不会生效。 因为target_include_directories的第一个参数需要指定目标。
...
add_library( 项目A ...) # add_executable(...)
...
target_include_directories( 项目A ...)
3.3 CMakeLists.txt完整脚本
# 指定CMake脚本解析的最低版本,
cmake_minimum_required(VERSION 3.18)
# 指定项目
project(HelloCMake)
# 引入脚本:参数为脚本文件的全路径
include(${CMAKE_CURRENT_SOURCE_DIR}/Common/CommonOutput.cmake)
# 用于可执行程序
add_executable(${PROJECT_NAME} # 参数1: 要生成的项目名称,这里对应的是HelloCMake, 而HelloCMake就是projec中的参数
${CMAKE_CURRENT_SOURCE_DIR}/src/main.cc # 参数2 : 项目所需的文件
${CMAKE_CURRENT_SOURCE_DIR}/include/typedef.h # 参数3: 项目所需的文件
)
# 指定 ${PROJECT_NAME}, 也就是 HelloCMake 的头文件搜索路径
target_include_directories( ${PROJECT_NAME} # 参数1 项目名称
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include # 参数2, 指定哪个搜索头文件路径, 这里的PRIVATE是cmake内置系统关键字,这里不展开,后面专门出一期文章说清楚
)
5. 结果
- CMake Tools 编译, 使用VSCode命令面板 (ctrl+shift+p):
>cmake:Build
- 项目编译结果:
[proc] Executing command: C:\major\development\tools\cmake_64\bin\cmake.exe --build c:/A/build --config Debug --target HelloCMake -j 14 --
[build] 用于 .NET Framework 的 Microsoft (R) 生成引擎版本 16.11.2+f32259642
[build] 版权所有(C) Microsoft Corporation。保留所有权利。
[build]
[build] main.cc
[build] C:\A\src\main.cc(1,1): warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失 [C:\A\build\HelloCMake.vcxproj]
[build] C:\A\include\Typedef.h(1,1): warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失 [C:\A\build\HelloCMake.vcxproj]
[build] HelloCMake.vcxproj -> C:\A\publish\x64\bin\debug64\HelloCMake.exe
[build] Build finished with exit code 0
可见项目已经编译成功
6 去掉 target_include_directories 调用
6.1 CMakeLists.txt脚本修改
- 简单修改CMakeLists.txt中的脚本,注释 target_include_directories的调用
# 指定CMake脚本解析的最低版本,
cmake_minimum_required(VERSION 3.18)
# 指定项目
project(HelloCMake)
# 引入脚本:参数为脚本文件的全路径
include(${CMAKE_CURRENT_SOURCE_DIR}/Common/CommonOutput.cmake)
# 用于可执行程序
add_executable(${PROJECT_NAME} # 参数1: 要生成的项目名称,这里对应的是HelloCMake, 而HelloCMake就是projec中的参数
${CMAKE_CURRENT_SOURCE_DIR}/src/main.cc # 参数2 : 项目所需的文件
${CMAKE_CURRENT_SOURCE_DIR}/include/typedef.h # 参数3: 项目所需的文件
)
# # 指定 ${PROJECT_NAME}, 也就是 HelloCMake 的头文件搜索路径
# target_include_directories( ${PROJECT_NAME} # 参数1 项目名称
# PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include # 参数2, 指定哪个搜索头文件路径, 这里的PRIVATE是cmake内置系统关键字,这里不展开,后面专门出一期文章说清楚
# )
VSCode编写CMake脚本中, 多行注释 与取消注释 快捷键: ctrl + /
6.2 项目编译结果
- 你瞧, 编译器报错提示,说找不到头文件
[build] C:\A\src\main.cc(2,10): fatal error C1083: 无法打开包括文件: “Typedef.h”: No such file or directory [C:\A\build\HelloCMake.vcxproj]
- 看图嘛, 一图胜千言。
7 总结
- 这下,可以将头文件和源文件分类存放,使得代码文件结构有序。解决之前需要将所有文件放在一个目录下的问题了。
完