CMake的用途,以及为什么需要CMake
CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程),或者说,CMake是构建工具的构建工具,因为在CMake出现之前,如果我们想让程序运行在不同的平台,就常常需要为不同的平台编写Makefile,去编译链接程序,而CMake的出现,使我们省去了为每个平台单独编写Makefile的麻烦,通过编写一次CMakeLists.txt文件,通过CMake工具去产生对应平台下的Makefile文件,做到了Once Code, Build Every Where.
CMake的历史
CMake最早作为ITK(www.itk.org)组织中的项目,开始于1999年,该组织是由美国国家医学图书馆(US National library of medicine提供资金援助。ITK组织内部拥有大量的软件运行不同的平台,因此需要专门针对不同的平台编写不同的编译复杂构建系统,为了解决上述问题该组织开发出CMake构建工具。
它的发展过程也初步经历了一下三个阶段:
-
~2000 (~v2.x) ,刚刚启动,过程式描述为主。 -
2000~2014 (v3.0~) ,引入Target概念。 -
2014~now (~v3.15),有了Target和Property的定义,更现代化。
CMake的使用
单源文件 - 最简单的CMakeLists.txt
我们通过编写CMakeLists.txt来构建目标,最简单的CMakeLists.txt如下
cmake_minimum_required(VERSION 3.0.0)
project(Main VERSION 0.1.0)
add_executable(Main main.cpp)
-
第一行指定了解析该CMakeLists.txt文件所需要的最低的CMake版本 -
第二行指定了项目名称为Main,并且设置该项目版本为0.1.0 -
第三行添加了构建目标Main,这里的Main可以和项目名称同名也可以不同名,并且指定构建Main目标需要main.cpp文件
如果目标只是单个源文件,其实也没必要用CMake是吗。
使用CMake去编译源文件
在上一段中,我们已经初步写好了CMakeLists.txt文件,那么怎么通过这个文件去产生构建目标文件呢?答案很简单。我们一般会在项目目录下新建build文件夹,并在build文件夹中执行cmake .. ,于是CMake会自动在build文件夹产生Makefile,于是我们可以执行make 来产生我们的目标文件。
多源文件 - 还是最简单的CMakeLists.txt
假设我们的项目目录下有src1.cpp 、src2.cpp 、main.cpp ,那么我们怎么去组合并且编译他们呢?答案也很简单。
cmake_minimum_required(VERSION 3.0.0)
project(Main VERSION 0.1.0)
add_executable(Main main.cpp src1.cpp src2.cpp)
我们此处假设所有的源文件均在同一目录,所以我们可以这样简单的在add_executable 中添加源文件,但要是文件分布在不同的文件夹中,我们有稍有些区别。还是假设所有的源文件在同一目录,但是源文件数量越来越多,我们不想手动去添加,有没有自动找到源文件,并且添加到add_executable 里的办法呢?有,答案时使用aux_source_directory(<dir> <variable>) 去收集<dir> 目录下的所有源文件名称,并且添加到变量<variable> 中,所以我们就可以这样写:
cmake_minimum_required(VERSION 3.0.0)
project(Main VERSION 0.1.0)
aux_directory(./ SRCS)
add_executable(Main ${SRCS})
我们这里跳过多目录多源文件的写法,感兴趣的读者可以自行查找相关方法。
在项目中使用第三方库
我们知道,绝大多数C/C++第三方库都会使用CMake作为它们项目的构建工具,所以我们也能很方便的用CMake来导入第三方库,并且去使用它们。比方说我们想使用fmtlib/fmt库,那么我们可以在项目目录中建立libs文件夹,并且在该目录下使用git submodule add https://github.com/fmtlib/fmt 去添加第三方库。于是CMakeLists.txt中只需要增加两行就可以很方便的导入fmt到项目了。
cmake_minimum_required(VERSION 3.0.0)
project(Main VERSION 0.1.0)
add_subdirectory(libs/fmt)
aux_directory(./ SRCS)
add_executable(Main ${SRCS})
target_link_libraries(Main fmt::fmt)
结语
本文虽然没有很深入地去谈一些CMake相关的命令和CMakeLists.txt的写法,只是给出了一些简单的例子。推荐大家可以看CMake官方文档中的Primer部分。
|