CMake-使用CMake创建并编译C++工程

CMake是什么

CMake是C++工程跨平台的构建工具.

CMake中对应的文件名称是CMakeLists.txt文件.

怎么用CMake

项目的某个目录都会有一个CMakeLists.txt.

一般来说都会新建一个目录, 把cmake的生成文件放到这个目录中:

mkdir build
cd build
cmake ..
make

注释

  • 单行注释是用#.
# 这是一个单行注释
  • 多行注释用#[[ ]]
#[[ 
    这是一个多行注释
]]

指定CMake的版本

一般来说, 在CMakeLists.txt的一开头, 都需要指定你的CMake的版本.

指定版本的语法是:

cmake_minimum_required(VERSION 你的版本号)

但是这个不需要非得指定, 一般来说, 在你本地调试好之后, 首先查看你本地的CMake版本:

cmake --version

然后在用这个写一个版本即可.

指定项目名称

可以用:

project(你的项目名字)

指定项目名称.

指定C++标准

一般来说一个C++工程有好多版本, 在命令行中可以通过-std=c++11来指定.

在cmake这样指定:

set (CMAKE_CXX_STANDARD 17)
set (CMAKE_CXX_STANDARD_REQUIRED ON)

这个就相当于-std=c++17.

其中set (CMAKE_CXX_STANDARD_REQUIRED ON)表示强制使用这个C++标准, 如果不支持这个C++标准就报错.

  • 如果不指定这个, 编译器会尝试使用这个C++标准, 但是如果用不了就会使用更低的C++标准.

指定可执行文件的输出路径

在CMake中这样指定:

set(EXECUTABLE_OUTPUT_PATH 你的路径)

其中这个路径可以是绝对路径, 也可以是相对路径.

  • 注意: 如果是相对路径, 是相对于cmake生成的Makefile的路径.

指定头文件搜索路径

include_directories(头文件搜索目录)

指定链接库

静态链接库

可以指定链接库的名字:

link_libraries(<static lib> [<static lib>...])
  • 注意这个名字可以是libxxx.a, 也就是全名.
  • 也可以是去掉lib.a的名字xxx.

也可以指定链接库的搜索路径:

link_directories(<lib path>)

动态链接库

动态链接库和静态链接库的设定不同.

首先指定动态链接库的搜索路径:

link_directories(<lib path>)

然后, 在生成可执行文件的命令之后, 需要加上链接库:

add_executable(haha ${SRC_LIST})
# 生成haha需要用到pthread
target_link_libraries(haha pthread)

指定编译选项

可以用add_compile_options指定编译选项:

add_compile_options ( 
    -Werror
  -Wall -Wextra -Winline -Winit-self -Wno-unused-function
  -Wuninitialized -Wno-sequence-point -Wno-inline -Wno-unknown-pragmas
  -Woverloaded-virtual -Wno-unused-parameter -Wno-missing-field-initializers -pipe
)

如果要对某几个可执行文件的编译指定编译选项:

add_executable(my_executable1 source1.cpp source2.cpp)
add_executable(my_executable2 source3.cpp source4.cpp)
add_compile_options(my_executable1 my_executable2 -Wall)

狠狠编译

搜索所有源文件

file(GLOB MAIN_RECURSE SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)

这一行会把src目录下面(如果有嵌套目录会递归搜索)中所有的cpp文件拿出来, 放到SRC这个变量中.

生成可执行文件

要生成可执行文件只需要:

add_executable(haha ${SRC})

其中haha就是可执行文件的名称.

生成静态链接库

生成静态链接库可以用:

add_library(haha STATIC ${SRC})

这就会生成libhaha.a.

生成动态链接库

add_library(calc SHARED ${SRC_LIST})

这个会生成libcalc.so

对接clangd

clangd需要一个compile_commands.json文件来解析源文件, CMake可以生成这个文件:

在CMakeList中, 加入:

set(CMAKE_EXPORT_COMPILE_COMMANDS 1)

然后使用cmake ..产生Makefile的时候, 也会产生compile_commands.json.

生成之后, 在你的项目中创建.clangd文件, 写入:

CompileFlags:
  CompilationDatabase: <compile_commands.json的路径>
  • 注意, 这个路径最后一定不要带`compile_commands.json`, 例如路径是`build/compile_commands.json`, 那么这里就指定`build/`

如果一个C/C++项目没有用cmake, 那么怎么生成compile_commands.json ?

如果项目用了Makefile, 直接使用bear工具, 用bear make xxx即可生成.

Bear的官网: https://github.com/rizsotto/Bear

一些有用的预定义宏

宏名称 含义
CMAKE_CURRENT_SOURCE_DIR CMakeList.txt所在的目录