cmake语法学习和vscode的应用
介绍
CMake 是一个跨平台的构建系统生成器,允许在不同的操作系统上生成对应的构建系统。CMake 生成的构建系统可以是 Makefile、Visual Studio 项目、Xcode 项目等。
通常来说,一般是在linux上开发和windows上开发用到比较多,然今就是大型项目中的模块管理也会用到。
本文主要介绍的是MINGWMinimalist GNU for Windows工具,是一个为 Windows 平台提供 GNU 工具链的软件包,它包括了一个 C 编译器(GCC),一个汇编器,一个链接器,以及其他的工具,这些工具都是 GNU 项目的一部分,用于替代 Windows 的系统工具。
在之后也会介绍cmake构建的的项目如何在visual studio 2022 或者 vscode上运行
电脑环境配置
本文电脑的下载的是vscode以及visual studio 2022(之前就安装好了)
然后是cmake包Cmake3.30_x86_64
最最要的MinGW-w64环境,安装参考这个blog参考
MinGW-64
Vscode的配置
没啥好配置的,就是安装一些插件啥的。
CMakeLists.txt的学习
进入正文之前,咱们需要了解一下配置,编译的语法:
在MinGW环境下:
1.构建配置,生成构建文件Makefile
参数解释:
-S 指定源目录 . 指的是当前目录
-G 指定生成器,将用来生成构建文件的类型。MinGW Makefiles,将生成适合 MinGW 环境使用的 Makefile
-DCMAKE_BUILD_TYPE=Debug 指定构建类型(build type),这将影响编译器的选项和链接器的行为
cmake -S . -B build -G 'MinGW Makefiles' -DCMAKE_BUILD_TYPE=Debug
--------------------------------------------------------------------------------------------
2. 构建项目
参数解释:
-C 在指定的目录build中执行操作
make -C build
=============================================================================================
在Visual Studio 环境中:
1.构建配置(如果是其他版本的,(Visual Studio 15 2017) (Visual Studio 16 2019)
cmake -S . -B build -G "Visual Studio 17 2022"
--------------------------------------------------------------------------------------------
2.构建项目
参数解释:
--build build指定构建目录
--config Release指定构建配置
cmake --build build --config Release
现在进入正文:
情况如下,windows中有一个大的工程叫做MyApp,里面有很多小模块,比如MyAdd,MyLog,MyCore等,采用模块化管理,将MyAdd模块生成静态库,将MyLog生成动态库,MyCore主程序调用它们。
文件组成目录
1.顶层CMakeLists.txt的编写
顶层CMakeLists.txt是用来组织整个大项目的,可以预先设置一些全局变量,输出路径,以及编译规则。
cmake_minimum_required(VEARSION 3.0)
# 项目名称,自定义
project(MyApp)
# 设置编译模式 Debug/Release
set(CMAKE_BUILD_TYPE Debug)
set(CMAKE_CXX_STANDARD 11)
# 针对某些编译器例如visual studio 开启文件组织功能
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
# 设置库,可执行文件的输出路径
set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
# 配置时候的消息输出
message(${LIBRARY_OUTPUT_PATH})
message(${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
# 添加子文件夹
add_subdirectory(MyAdd)
add_subdirectory(MyLog)
add_subdirectory(MyCore)
2.Mycore主模块CMakeLists.txt编写
在Mycore的src目录下新建一个测试文件,main.cpp,测试内容如下:
#include <iostream>
using namespace std;
int main()
{
cout << "hello world" << endl;
return 0;
}
在Mycore目录下创建一个CMakeLists.txt文件,内容如下:
cmake_minimum_required(VERSION 3.0)
# 项目名称,自定义
project(mycore)
# 模块需要包含的头文件目录
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
# 模块需要的源文件
# 知识点:
# GLOB_RECURSE是寻找该模块CMakeLists.txt所在目录下的所有cpp文件,包括子目录
# GLOB 是寻找该模块CMakeLists.txt所在目录下的所有cpp文件,不包括子目录
file(GLOB_RECURSE SRC "*.cpp")
# 生成可执行文件
add_executable(MYAPP ${SRC})
然后进入vscode的终端:在项目myapp这一级输入
cmake -S . -B build -G 'MinGW Makefiles' -DCMAKE_BUILD_TYPE=Debug
出现下面的就是配置构建成功
– Configuring done
– Generating done
然后还是这一级输入:
make -C build
出现100%就生成可执行文件了,然后进入bin文件夹中就可以运行了。这也说明整个环境没问题,就可以进行下一步了。
3. MyAdd模块CMakeLists.txt编写(生成静态库给主模块调用)
在MyAdd文件夹下的src和include中分别创建myadd.cpp和myadd.h,内容如下:
在MyAdd目录下创建一个CMakeLists.txt文件,内容如下:
cmake_minimum_required(VERSION 3.0)
project(myadd)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
file(GLOB_RECURSE SRC "*.cpp")
# 生成静态库,参数是STATIC【还有SHARED参数,动态库】
# ${PROJECT_NAME} 获取的是project(myadd)中的myadd
# 会生成libmyadd.a的静态库
# 为什么不是windows下的lib呢?因为采用的是MinGW环境,生成的的linux下是一样的
add_library(${PROJECT_NAME} STATIC ${SRC})
4. MyLog模块CMakeLists.txt编写(生成动态库给主模块调用)
在MyLog文件夹下的src和include中分别创建mylog.cpp和myadd.h,内容如下:
在MyLog目录下创建一个CMakeLists.txt文件,内容如下:
cmake_minimum_required(VERSION 3.0)
project(mylog)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
file(GLOB_RECURSE SRC "*.cpp")
# 生成动态库,参数是SHARED
# 会生成libmylog.dll的动态库 以及一个libmylog.dll.a的静态库指明导入信息
add_library(${PROJECT_NAME} SHARED ${SRC})
# 预编译定义信息,PRPRIVATE私有,类似于c++中的类
add_compile_definitions(${PROJECT_NAME} PRPRIVATE MYLOG_LIBRARY)
5.在MyCore中组织模块并且进行调用
main.cpp中的编写
MyCore中的CMakeLists.txt修改
cmake_minimum_required(VERSION 3.0)
# 项目名称,自定义
project(mycore)
# 模块需要包含的头文件目录
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
# 模块需要的源文件
# 知识点:
# GLOB_RECURSE是寻找该模块CMakeLists.txt所在目录下的所有cpp文件,包括子目录
# GLOB 是寻找该模块CMakeLists.txt所在目录下的所有cpp文件,不包括子目录
file(GLOB_RECURSE SRC "*.cpp")
# 生成可执行文件
add_executable(MYAPP ${SRC})
# 添加下面语法
# 链接第三方库,直接是每个库CMakeLists.txt的project名字
target_link_libraries(MYAPP PUBLIC myadd mylog)
# 目标文件需要第三方库的头文件目录
target_include_directories(MYAPP PUBLIC ${CMAKE_SOURCE_DIR}/MyAdd/include
${CMAKE_SOURCE_DIR}/MyLog/include
)
6.编译运行
进入vscode的终端:在项目myapp这一级输入
cmake -S . -B build -G 'MinGW Makefiles' -DCMAKE_BUILD_TYPE=Debug
出现下面的就是配置构建成功
– Configuring done
– Generating done
然后还是这一级输入:
make -C build
出现100%就生成可执行文件了,然后进入bin文件夹中就可以运行了。
运行调试配置
那平时开发肯定会有bug,那么就需要进行调试来解决bug
如果每次都要手动进行命令的输入,很麻烦。
这时候就需要用的vscode的配置来简化工作。
1.直接在MYAPP目录新建.vscode
目录
2.在.vscode
目录创建task.json
文件
通用内容如下:里面最好不要有注释
{
"version": "2.0.0",
"tasks": [
{
"label": "CMake: configure",
"type": "shell",
"command": "cmake",
"args": [
"-S",
".",
"-B",
"build",
"-G",
"MinGW Makefiles",
"-DCMAKE_BUILD_TYPE=Debug"
],
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": ["$msCompile"]
},
{
"label": "CMake: build",
"type": "shell",
"command": "make",
"args": [
"-C",
"build",
],
"group": {
"kind": "build",
"isDefault": true
},
"dependsOn": "CMake: configure",
"problemMatcher": ["$msCompile"]
}
]
}
然后ctrl + shift + b
会出来两个选项如下
直接选择CMake: build
就直接配置和编译ok了
3. 在.vscode
目录创建launch.json
文件
这个文件是用来配置调试功能的,这个需要做一点修改:修改之后把注释去掉
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch myapp",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/bin/MYAPP.exe",// 这里需改为自己的可执行文件位置
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}/build",
"environment": [],
"externalConsole": false,
"preLaunchTask": "CMake: build",
"internalConsoleOptions": "openOnSessionStart",
"logging": {
"moduleLoad": false,
"trace": false,
"engineLogging": false,
"programOutput": true,
"exceptions": false
},
"miDebuggerPath": "D:/mingw64/bin/gdb.exe",// 这里需改为自己的gdb位置
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
}
]
}
然后点击,就可以进行调试了
补充Visual Studio 环境的构建配置和运行调试配置
通用tasks.json内容如下:里面最好不要有注释
{
"version": "2.0.0",
"tasks": [
{
"label": "CMake: configure",
"type": "shell",
"command": "cmake",
"args": [
"-S",
".",
"-B",
"build",
"-G",
"Visual Studio 17 2022"
],
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": ["$msCompile"]
},
{
"label": "CMake: build",
"type": "shell",
"command": "cmake",
"args": [
"--build",
"build",
"--config",
"Debug"
],
"group": {
"kind": "build",
"isDefault": true
},
"dependsOn": "CMake: configure",
"problemMatcher": ["$msCompile"]
}
]
}
launch.json文件修改:修改之后把注释去掉
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch myapp",
"type": "cppvsdbg", // 这里是cppvsdbg
"request": "launch",
"program": "${workspaceFolder}/build/bin/Debug/MYAPP.exe",// 这里需改为自己的可执行文件位置,
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}/build",
"environment": [],
"externalConsole": false,
"preLaunchTask": "CMake: build",
"internalConsoleOptions": "openOnSessionStart",
"logging": {
"moduleLoad": false,
"trace": false,
"engineLogging": false,
"programOutput": true,
"exceptions": false
}
]
}
]
}
插一句话,你都安装的visual studio 直接在里面调试就ok啊,那个功能还强大,最多就是要cmake配置一下就行。
将自己的库如何给其他程序使用
前面介绍了将自己的模块打包成库文件给主函数使用
如果我们想把这个模块给其他人使用(提供源码),并且可以调试,该如何使用呢
首先,我们可以把生成好的库文件,源文件,头文件分别放好,如下图
然后放入自己需要调用的工程中,在需要链接的项目中,编写CMakeLists.txt
这里就不贴出来了,主要是添加如下语句
# 第三方的头文件目录
target_include_directories(${CMAKE_SOURCE_DIR}/mylib/include)
# 第三方的库文件目录
target_link_directories(MYAPP PUBLIC ${CMAKE_SOURCE_DIR}/mylib/libs)
# 链接第三方库文件
target_link_libraries(MYAPP PUBLIC mylog myadd)
# 自定义指定,在项目构建完成后执行的指令,用于打印信息,复制文件,执行脚本都可以
# MYAPP是我的项目名称,这里自定义修改
# copy_directory是拷问下面文件夹下的所有文件到目标文件夹下$<TARGET_FILE_DIR:MYAPP>,同样只要修改MYAPP
# COMMENT 打印信息
# VERBATIM 建议带上,参数逐字解释,防止字符转义问题。
add_custom_command(
TARGET MYAPP
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
${CMAKE_SOURCE_DIR}/mylib/libs
$<TARGET_FILE_DIR:MYAPP>
COMMENT "Copying MyLibrary.dll to target directory"
VERBATIM
)
最后就是修改launch.json文件,防止调试找不到cpp的路径,只需要添加映射关系:源文件目录:更改后的目录
"sourceFileMap":
{
"path/MyApp/MyAdd/src": "${workspaceFolder}/mylib/src"
}
大功告成,初步的入门就是这样达成了,后面如果有机会会继续完善。