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。
#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)
跟人觉得,如果没有编译为库的需求,还是使用第二种方式比较好。
引用外部静态库和动态库欢迎分享,转载请注明来源:内存溢出
评论列表(0条)