VSCode+mingw64+cmake

VSCode+mingw64+cmake,第1张

VSCode+mingw64+cmake cmake简介

cmake安装:Download | CMake。

在这之前,我们介绍一下cmake。虽然Make和Makefile简化了手动构建的过程,但是编写Makefile文件仍然是一个麻烦的工作,因此就有了CMake工具。CMake工具用于生成Makefile文件,而如何生成Makefile文件,则由CMakeLists.txt文件指定。它们直接的关系如下图:

使用cmake生成Makefile并编译的流程如下:

编写CMake配置文件CMakeLists.txt。执行命令 cmake path生成CMakefile。其中,path为CMakeLists.txt所在的目录。使用make命令进行编译。

具体的cmake语法这里就不介绍了。

使用VSCode快速创建项目

使用命令CMake:Quick Start就会创建一个CMakeLists.txt文件。如果想手动创建也可以的。

然后我们需要选择一个kit,就是上图下面的选框,其实选择的就是编译器:

注意,这里VSCode会自动在电脑中寻找已存在的编译器,但是笔者也碰到过GCC编译器目录不在的情况,这个时候可以手动修改配置文件:C:UsersDELLAppDataLocalCMakeToolscmake-tools-kits.json。

完成了这些,我们就可以进行build和debug了,快捷方式同样在底部菜单栏。首次build的时候打印日志如下:

[main] Building folder: Demo 
[main] The folder containing the CMake cache is missing. The cache will be regenerated.
[main] Configuring folder: Demo 
[proc] Executing command: "D:\Program Files\CMake\bin\cmake.exe" --no-warn-unused-cli -DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE -DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo -DCMAKE_C_COMPILER:FILEPATH=D:msys64mingw64bingcc.exe -DCMAKE_CXX_COMPILER:FILEPATH=D:msys64mingw64bing++.exe -Hd:/02Personal/Project/Demo -Bd:/02Personal/Project/Demo/build -G "MinGW Makefiles"
[cmake] Not searching for unused variables given on the command line.
[cmake] -- The C compiler identification is GNU 11.2.0
[cmake] -- The CXX compiler identification is GNU 11.2.0
[cmake] -- Detecting C compiler ABI info
[cmake] -- Detecting C compiler ABI info - done
[cmake] -- Check for working C compiler: D:/msys64/mingw64/bin/gcc.exe - skipped
[cmake] -- Detecting C compile features
[cmake] -- Detecting C compile features - done
[cmake] -- Detecting CXX compiler ABI info
[cmake] -- Detecting CXX compiler ABI info - done
[cmake] -- Check for working CXX compiler: D:/msys64/mingw64/bin/g++.exe - skipped
[cmake] -- Detecting CXX compile features
[cmake] -- Detecting CXX compile features - done
[cmake] project_source_dir:D:/02Personal/Project/Demo
[cmake] project_binary_dir:D:/02Personal/Project/Demo/build
[cmake] -- Configuring done
[cmake] -- Generating done
[cmake] -- Build files have been written to: D:/02Personal/Project/Demo/build
[build] Starting build
[proc] Executing command: "D:\Program Files\CMake\bin\cmake.exe" --build d:/02Personal/Project/Demo/build --config RelWithDebInfo --target all -j 10 --
[build] [ 50%] Building CXX object CMakeFiles/DemoOne.dir/main.cpp.obj
[build] [100%] linking CXX executable DemoOne.exe
[build] [100%] Built target DemoOne
[build] Build finished with exit code 0

关键的是其中的两个cmake命令。但是在这整个过程中,我们还是有很多疑惑的,那么下面一一解答。

CMakeLists.txt中内容是啥

默认生成的内容如下:

 #需要的最低版本
cmake_minimum_required(VERSION 3.0.0)
#配置项目名称和版本
project(DemoOne VERSION 0.1.0) 

#启动测试功能
include(CTest)
enable_testing()

#编译可执行文件(可执行文件名称 源文件)
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) #指定exe路径
add_executable(DemoOne main.cpp)

#设置打包功能:打包压缩包名称和版本
set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
include(CPack)

SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
PROJECT_BINARY_DIR为默认情况下的二进制程序路径,这里为build/;此语句将指定程序最终生成可执行程序的路径为build/bin。

message输出
#print message
message(project_source_dir:${PROJECT_SOURCE_DIR})
message(project_binary_dir:${PROJECT_BINARY_DIR})

设置了project之后,就会引入两个已定义好的变量。可以使用message打印看看。

指定编程语言版本
set(CMAKE_C_STANDARD 99)
set(CMAKE_CXX_STANDARD 11)

这里设置的变量都是CMAKE_开头(包括project命令自动设置的变量),这类变量都是CMake的内置变量,正是通过修改这些变量的值来配置CMake构建的行为。

CMAKE_、_CMAKE或者以下划线开头后面加上任意CMake命令的变量名都是CMake保留的。

配置编译选项

通过命令add_compile_options命令可以为所有编译器配置编译选项(同时对多个编译器生效); 通过设置变量CMAKE_C_FLAGS可以配置c编译器的编译选项; 而设置变量CMAKE_CXX_FLAGS可配置针对c++编译器的编译选项。 比如:

add_compile_options(-Wall -Wextra -pedantic -Werror)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pipe -std=c99")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pipe -std=c++11")
配置编译类型

通过设置变量CMAKE_BUILD_TYPE来配置编译类型,可设置为:Debug、Release、RelWithDebInfo、MinSizeRel等,比如:

set(CMAKE_BUILD_TYPE Debug)

当然,更好的方式应该是在执行cmake命令的时候通过参数-D指定:

cmake -B build -DCMAKE_BUILD_TYPE=Debug

如果设置编译类型为Debug,那么对于c编译器,CMake会检查是否有针对此编译类型的编译选项CMAKE_C_FLAGS_DEBUG,如果有,则将它的配置内容加到CMAKE_C_FLAGS中。

可以针对不同的编译类型设置不同的编译选项,比如对于Debug版本,开启调试信息,不进行代码优化:

set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g -O0")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -O0")

对于Release版本,不包含调试信息,优化等级设置为2:

set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O2")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2")

也可以在VScode界面底部菜单栏进行设置。

同一目录多源文件

#查找指定目录下所有的源文件,然后把结果保存进指定的变量名
aux_source_directory(. src_dir)
#编译可执行文件(可执行文件名称 源文件)
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) #指定exe路径
add_executable(${PROJECT_NAME} ${src_dir})
多目录多源文件 子目录编译为链接库

对于这种情况,我们需要在每一个目录中编写一个CMakeLists.txt文件,然后各自编译为静态链接库,再在可执行文件中添加该链接库。

对于math文件夹中的CMakeLists.txt:

#查找指定目录下所有的源文件,然后把结果保存进指定的变量名
 aux_source_directory(. src_math)
 #编译静态链接库(静态链接库名称 源文件)
 SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)# 指定库的路径
 add_library(math ${src_math})

然后是可执行文件的CMakeLists.txt:

#添加子目录
add_subdirectory(math)

#查找指定目录下所有的源文件,然后把结果保存进指定的变量名
aux_source_directory(. src_main)

#编译可执行文件(可执行文件名称 源文件)
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) #指定exe路径
add_executable(${PROJECT_NAME} ${src_main})

#添加链接库 math是子目录中编译的库
target_link_libraries(${PROJECT_NAME} math)

用LIBRARY_OUTPUT_PATH指定最终静态库或者动态库的生成路径,所以这里最终的libmath.a静态库将在build/lib目录下生成

ADD_EXECUTABLE()用来构建可执行程序,这里用ADD_LIBRARY()来构建静态库或者动态库

ADD_LIBRARY(libname [SHARED|STATIC|MODULE] [EXCLUDE_FROM_ALL]

libname代表要生成的静态库或者动态库的名字,名字前不用带lib 系统会自动加上。比如要生成libmath库名,写math就好[SHARED|STATIC|MODULE] 分别表示构建动态库(一般.so结尾,mac os 系统为.dyld)、(.a)静态库、动态库(mac os 系统为.so,如果不支持 则当做SHARED看待);默认参数为STATICEXCLUDE_FROM_ALL 意思是这个库不会被默认构建,除非有其他的组件依赖或者手工构建。

当然,也可以同时生成动态库和静态库。

#查找指定目录下所有的源文件,然后把结果保存进指定的变量名
 aux_source_directory(. src_math)
 #编译可执行文件(可执行文件名称 源文件)
 SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)# 指定库的路径
 add_library(math SHARED ${src_math})#动态库
 # 给动态库添加版本号
 SET_TARGET_PROPERTIES(math PROPERTIES VERSION 1.2 SOVERSION 1) #VERSION 指代动态库版本,SOVERSION 指代API版本。

 add_library(static_math STATIC ${src_math})#静态库
 # 改变最终生成的静态库的名字
 SET_TARGET_PROPERTIES(static_math PROPERTIES OUTPUT_NAME math)
 #获取指定构建目标的指定属性的值;这里获取math_static的属性OUTPUT_NAME值赋值给OUTPUT_VALUE变量
 GET_TARGET_PROPERTY(OUTPUT_VALUE static_math OUTPUT_NAME)
添加子目录源文件到编译列表

上述方法是将子目录编译为一个库,那么编译结果会多一些库文件。但是其实,我们可以将各子目录全部添加到编译列表,这样子目录就不需要CMakeLists.txt文件了。

 #需要的最低版本
cmake_minimum_required(VERSION 3.0.0)
#配置项目名称和版本
project(DemoOne VERSION 0.1.0) 

#print message
message(STATUS "root This is BINARY dir " ${PROJECT_BINARY_DIR})
message(STATUS "root This is SOURCE dir " ${PROJECT_SOURCE_DIR})

#启动测试功能
include(CTest)
enable_testing()

#查找指定目录下所有的源文件,然后把结果保存进指定的变量名
aux_source_directory(. src_main)
aux_source_directory(./math src_main)
#编译可执行文件(可执行文件名称 源文件)
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) #指定exe路径
add_executable(${PROJECT_NAME} ${src_main})

#设置打包功能:打包压缩包名称和版本
set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
include(CPack)

跟人觉得,如果没有编译为库的需求,还是使用第二种方式比较好。

引用外部静态库和动态库

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5713752.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存