介绍
CMake 是一个跨平台的自动化构建系统,它使用配置文件(称为 CMakeLists.txt)来生成标准的构建文件,如 Unix 的 Makefile 或 Windows 的 Visual Studio 工程文件。CMake 能够支持多种编程语言,尤其是 C 和 C++,并且可以与多种编译器和构建工具配合使用。
以下是 CMake 的一些关键特点:
-
跨平台支持: CMake 支持在 Windows、Linux、macOS 等多种操作系统上构建项目。
-
生成多种构建系统: CMake 可以生成多种构建系统的文件,包括 Make、Ninja、Xcode 和 Visual Studio 解决方案等。
-
模块化: CMake 提供了模块化的设计,允许开发者重用代码和设置。
-
自定义构建类型: CMake 允许定义不同的构建类型,如 Debug、Release 或自定义构建类型。
-
依赖管理: CMake 可以处理复杂的依赖关系,并自动下载和集成第三方库。
-
测试驱动开发(TDD): CMake 支持 CTest,这是一个测试驱动开发工具,可以轻松地集成到构建过程中。
-
安装和打包: CMake 提供了安装目标和打包支持,可以生成安装程序和软件包。
-
变量和条件逻辑: CMake 脚本使用变量和条件逻辑来控制构建过程,使得构建配置非常灵活。
-
查找和配置外部库: CMake 可以查找和配置外部库,使得集成第三方库变得简单。
-
多配置工具: CMake 支持多配置工具,这意味着它可以生成支持多个配置(如 Debug 和 Release)的构建系统。
-
IDE 集成: CMake 可以生成 IDE 项目文件,如 Visual Studio 或 Xcode 项目,使得在这些环境中工作变得容易。
CMake 的基本工作流程包括:
- 编写
CMakeLists.txt
文件,定义项目的构建规则和配置。 - 运行
cmake
命令,指定源代码目录和构建目录,生成构建系统。 - 使用生成的构建系统(如 Make 或 IDE)来编译和构建项目。
CMake 是许多开源项目和商业软件的首选构建系统,因为它的灵活性和强大的功能使得它能够适应各种复杂的构建需求。
外部构建
可能有人会问,它不能像Makefile一样直接make clean 或者make distclean清除编译的垃圾文件吗,我当时学的时候也谷歌过,但是,很遗憾没有,使用我才让它产生的垃圾文件放在build目录下,其实不能说是垃圾文件,只不过是一些中间文件,记录某些东西的,我用不上它,所以认为是垃圾…仅此而已。
对此官方的解释是:
CMakeLists.txt 可以执行脚本并通过脚本生成一些临时文件,但是却没有办法来跟踪这些临时文件到底是哪些,因此,没有办法提供一个可靠的 clean 方案。
CMAKE常用示例
链接多个动态库示例
set(LIBRARY_NAMES pub jsoncpp )
set(LIBRARIES)
foreach(LIBRARY_NAME ${LIBRARY_NAMES})
#清除旧缓存,强制重新查找
unset(LIBRARY_PATH CACHE)
find_library(LIBRARY_PATH ${LIBRARY_NAME} ${LIBDIR} )
if(NOT LIBRARY_PATH)
message(FATAL_ERROR "Could not find library ${LIBRARY_NAME}")
endif()
message(" find library ${LIBRARY_NAME} ${LIBRARY_PATH}")
list(APPEND LIBRARIES ${LIBRARY_PATH})
message(" LIBRARIES ${LIBRARIES} ")
endforeach()
target_link_libraries(relay_ticket_check_server ${LIBS} ${LIBRARIES}) #链接可执行程序
指定编译选项
set(CMAKE_CXX_STANDARD 11) #测试不会生效
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF) #禁用编译器特有的扩展(可选,推荐)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -w -std=c++11 ") #启动c++11和忽略警告
set(EXECUTABLE_OUTPUT_PATH $ENV{HOME}/bin ) #设置输出路径
常用的命令
指定最低版本:cmake_minium_required
指定使用的cmake最低版本
定义工程名称:protect
定义工程名称
生成可执行程序:add_executable
定义工程会生成一个可执行程序,生成的程序,和项目名没有关系。
执行cmake生成形式
执行版本为 Debug还是Release,有时候构建报错::-1: error: No "Debug" CMake configuration found. Available configuration: "".
Make sure that CMAKE_BUILD_TYPE variable matches the "Build type" field. 就需要添加这个参数
执行cmake
注意
在Windows下使用cmake .. 会生成vs的项目架构。不会生成MakeFile文件,如果windows下想要生成MakeFile需要输入命令 cmake ../ -G "Unix Makefiles"。来生成,最后执行make命令进行项目的编译。
这里有些人使用 cmake ../ -G "Unix Makefiles会报错:
要保证 MinGW 的 bin 目录(例如 C:\MinGW\bin
)已经添加到系统的 PATH 环境变量中。
配置完成后,关闭终端在尝试,即可正常使用。
这里要是失败,可以使用 cmake .. -G "MinGW Makefiles" 代替,编译完成后使用mingw32-make.exe进程构建。
cmake的环境变量设置为:D:\C++\Qt\Tools\mingw810_64\bin
先输入cmake ../ -G "MinGW Makefiles" 然后输入mingw32-make
先输入cmake ../ -G "Unix Makefiles" 然后输入make
先输入cmake ..生成vs项目然后使用vs构建。
私人定制
定义变量:set
指定使用的C++标准:CMAKE_CXX_STANDARD
指定输出路径:EXECUTABLE_OUTPUT_PATH
如果指定的路径不存在,那么cmake会自动创建多层级的目录。
搜索文件
方式一:aux_source_directory
PROJECT_SOURCE_DIR:搜索cmake 执行后后面指定路径的当前源文件路径下的文件.c .cpp ,添加到SRC_LISTS中
方式二:file
CMAKE_CURRENT_SOURCE_DIR: CMAKE文件所对应的路径 经过本人亲测:file只搜索cpp文件,也是可以编译通过的。file 可以作拷贝的功能。
包含头文件路径:include_directories
或者写入绝对路径:绝对路径使用“”包含,路径中使用/进行链接,不能使用\。
link_directories
链接动态库的目录,看起来不能够生效。。。
通过CMAKE制作库文件add_library
静态库就是STATIC,动态库就是SHARED。
指定动态库的输出路径
链接静态库 :link_libraries
链接动态库:target_link_libraries
如果程序中要使用多条这样的句子,那么必须保证,每种都指定权限。否则,会报错。
target_link_libraries(simple1 PUBLIC ${VTKLIBS} ) #当target_link_libraries出现多次时,需要明确指出用public
打印日志
在CMake
构建的时候,你可能不知道某些变量是啥内容,那么就在终端打印出来看看就好了,这根我们写代码中的printf函数差不多,给直接打一串字符串出来瞧瞧…
file(GLOB VTKLIBS E:/VTK/vs_install/lib/*.lib)
message(VTKLIBS = ${VTKLIBS})
这个还可以用于拷贝:file(COPY ${ASSETS} DESTINATION ${CMAKE_BINARY_DIR} )
添加子目录
add_subdirectory(wrapper) wrapper为子目录名称
在子目录里可以链接静态库,使用add_library(wrapper ${WRAPPER})
将所有cpp文件链接到这个wrapper lib库中。 默认生成静态库,动态库编译不过去
宏定义:add_definitions
在 CMake 中,add_definitions
命令用于向编译器添加宏定义。这在你需要在编译时定义一些预处理器宏时非常有用。add_definitions
是 CMake 的一个函数,它允许你指定一组宏定义,这些宏定义会在编译时被添加到编译器的命令行中。
以下是如何使用 add_definitions
的基本语法:
add_definitions(-DMY_MACRO)
在这个例子中,-DMY_MACRO
会被添加到编译器的命令行中,这样在编译过程中 MY_MACRO
就会被定义。
使用 target_compile_definitions
添加特定目标的宏定义
如果你只想为某个特定目标添加宏定义,可以使用 target_compile_definitions
函数。这允许你为特定的目标(例如可执行文件或库)指定一组宏定义。
add_executable(my_executable source1.cpp source2.cpp)
target_compile_definitions(my_executable PRIVATE -DMY_MACRO)
使用 target_compile_definitions
添加多个宏定义
你可以一次性添加多个宏定义:
target_compile_definitions(my_executable PRIVATE
-DMY_MACRO
-DOTHER_MACRO=value
)
这会在编译 my_executable
时定义 MY_MACRO
和 OTHER_MACRO
。
在 CMakeLists.txt
中使用
在 CMakeLists.txt
文件中使用 add_definitions
通常是为了全局地添加宏定义,影响所有的目标。例如:
cmake_minimum_required(VERSION 3.1)
project(MyProject)
add_definitions(-DMY_MACRO)
add_executable(my_executable source1.cpp source2.cpp)
在这个例子中,MY_MACRO
会被定义在所有的目标中。
注意事项
-
宏定义的值:如果宏定义需要一个值,确保在宏名称和值之间有空格,或者使用
$<value>
语法。 -
条件编译:如果你只想在特定条件下添加宏定义,可以使用
if
语句来控制。 -
清理:在某些情况下,你可能需要在清理构建目录时删除由宏定义生成的文件。
通过使用 add_definitions
和 target_compile_definitions
,你可以灵活地控制编译时的宏定义,从而影响编译行为。这对于调试、特性切换或平台特定的编译非常有用。
使用cmake命令行构建MSVC编译器项目。
我们在Qtcreator中可以直接在界面上点击构建就可以生成项目,但是如何用命令行进行构建呢?如何目录向Qtcreator一样清晰呢?
在 Windows 上使用 CMake 命令行指定使用 MSVC(Microsoft Visual C++)编译器进行编译,可以通过以下步骤实现:
1. 确保安装了必要的工具
-
安装 Visual Studio:确保安装了 Visual Studio,并且安装了 C++ 开发工具集。可以通过 Visual Studio 安装程序来安装。
-
安装 CMake:确保安装了 CMake,并且将其添加到系统的 PATH 环境变量中,这样可以在命令行中直接使用
cmake
命令。
2. 打开命令提示符或终端
打开命令提示符(CMD)或 PowerShell。
3. 使用 CMake 指定编译器
在命令行中,进入你的项目目录,然后使用以下命令来指定使用 MSVC 编译器。
方法一:指定生成器
CMake 允许通过 -G
参数指定生成器。对于 MSVC,可以指定为 Visual Studio
,并指定版本号和平台。例如:
cmake -G "Visual Studio 17 2022" -A x64 ..
-
-G "Visual Studio 17 2022"
:指定使用 Visual Studio 2022 作为生成器。17
是 Visual Studio 2022 的内部版本号。 -
-A x64
:指定目标平台为 64 位。如果你的目标平台是 32 位,可以使用-A Win32
。 -
通过cmake -h 查看手册
方法二:设置环境变量
如果不想在命令行中每次都指定生成器,可以通过设置环境变量来指定编译器。在命令行中运行以下命令:
set CC=cl
set CXX=cl
cmake ..
-
set CC=cl
:设置 C 编译器为 MSVC 的cl.exe
。 -
set CXX=cl
:设置 C++ 编译器为 MSVC 的cl.exe
。 -
cmake ..
:运行 CMake 配置命令。
4. 构建项目
配置完成后,可以使用以下命令来构建项目:
cmake --build . --config Release
-
--build .
:指定构建目录为当前目录。 -
--config Release
:指定构建配置为 Release。如果需要构建 Debug 版本,可以将Release
替换为Debug
。
5. 示例
假设你的项目目录结构如下:
复制
my_project/
├── CMakeLists.txt
├── src/
│ └── main.cpp
在 my_project
目录下创建一个 build
目录,然后进入该目录:
cd my_project
mkdir build
cd build
运行以下命令来配置和构建项目:
cmake -G "Visual Studio 17 2022" -A x64 ..
cmake --build . --config Release
注意事项
-
确保 Visual Studio 的安装路径已添加到系统的 PATH 环境变量中,否则可能找不到
cl.exe
。 -
如果使用的是较旧版本的 Visual Studio,需要将生成器名称和版本号替换为对应的值。例如,对于 Visual Studio 2019,可以使用
-G "Visual Studio 16 2019"
。 -
如果项目中使用了特定的工具链文件,可以在 CMake 命令中通过
-DCMAKE_TOOLCHAIN_FILE=<path>
参数指定工具链文件路径。
通过以上步骤,你就可以在 Windows 上使用 CMake 命令行指定使用 MSVC 编译器来编译项目了。
但是这样生成的build目录还会残留VS的一些配置,后续在看看有什么办法可以给他去掉???(cmake使用MSVC构建应该是使用的Ninja。使用的是cl.exe)安装位置在:D:\software\Microsoft Visual Studio\2019\Common7\IDE\CommonExtensions\Microsoft\CMake\Ninja/ninja.exe
文章参考:【cmake】关于cmake构建系统Ninja_cmake ninja-CSDN博客。
不过要注意:需要将ninja路径配置到环境变量里,不然会报错:
这将生成一个Ninja构建文件(build.ninja
)并配置项目。然后输入ninja
但是这边好像有个坑,这样默认使用MinGW编译的。。。期待来个大佬给指点指定。