CMake入门实践 什么是cmake
Posted 谢小小XH
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CMake入门实践 什么是cmake相关的知识,希望对你有一定的参考价值。
一.CMake简介
CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程)。他能够输出各种各样的makefile或者project文件,能测试编译器所支持的C++特性,类似UNIX下的automake。只是 CMake 的组态档取名为 CMakeLists.txt。Cmake 并不直接建构出最终的软件,而是产生标准的建构档(如 Unix 的 Makefile 或 Windows Visual C++ 的projects/workspaces),然后再依一般的建构方式使用。这使得熟悉某个集成开发环境(IDE)的开发者可以用标准的方式建构他的软件,这种可以使用各平台的原生建构系统的能力是 CMake 和 SCons 等其他类似系统的区别之处。
cmake 的特点主要有:
- 开放源代码,使用类 BSD 许可发布。http://cmake.org/HTML/Copyright.html
- 跨平台,并可生成 native 编译配置文件,在 Linux/Unix 平台,生成 makefile,在苹果平台,可以生成 xcode,在 Windows 平台,可以生成 MSVC 的工程文件。
- 能够管理大型项目,KDE4 就是最好的证明。
- 简化编译构建过程和编译过程。Cmake 的工具链非常简单:cmake+make。
- 高效虑,按照 KDE 官方说法,CMake 构建 KDE4 的 kdelibs 要比使用 autotools 来构建 KDE3.5.6 的 kdelibs 快 40%,主要是因为 Cmake 在工具链中没有 libtool
- 可扩展,可以为 cmake 编写特定功能的模块,扩充 cmake 功能。
在 linux 平台下使用 CMake 生成 Makefile 并编译的流程如下:
- 编写 CMake 配置文件 CMakeLists.txt 。
- 执行命令 cmake PATH 或者 ccmake PATH 生成 Makefile。其中, PATH 是 CMakeLists.txt 所在的目录。
- 使用 make 命令进行编译。
二.Hello World
没有”Hello World”的教程不是好教程.这里首先举一个Hello world的例子给大家做一个对于CMake的感性理解.
详细的项目代码可以见: LearningCMake/HelloWorld/
比如我现在项目目录叫做HelloWorld
,其中建立两个文件,分别是main.cpp
和 CMakeLists.txt
(注意文件名大小写):
main.cpp文件中就是非常简单的输出Hello world的代码了,如下:
//main.cpp
#include <iostream>
int main()
std::cout << "Hello, World!" << std::endl;
return 0;
CmakeLists.txt 文件内容:
cmake_minimum_required(VERSION 3.9)
project(HelloWorld)
set(CMAKE_CXX_STANDARD 11)
add_executable(HelloWorld main.cpp)
所有的文件创建完成后,HelloWorld
目录中应该存在 main.cpp
和 CMakeLists.txt
两个文件. 接下来我们来构建这个工程,在这个目录运行:
cmake .
注意命令后面的点号,代表本目录.
输出大概是这个样子:
-- The C compiler identification is GNU 5.4.0
-- The CXX compiler identification is GNU 5.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/enningxie/xiekun/WorkSpace/LearningCMake/HelloWorld
再让我们看一下目录中的内容:
你会发现,系统自动生成了:CMakeFiles
, CMakeCache.txt
, cmake_install.cmake
等文件,并且生成了Makefile
. 现在不需要理会这些文件的作用,以后你也可以不去理会。最关键的是,它自动生成了Makefile
.
然后进行工程的实际构建,在这个目录输入make
命令,大概会得到如下的彩色输出:
Scanning dependencies of target HelloWorld
[ 50%] Building CXX object CMakeFiles/HelloWorld.dir/main.cpp.o
[100%] Linking CXX executable HelloWorld
[100%] Built target HelloWorld
如果你需要看到 make 构建的详细过程,可以使用 make VERBOSE=1
来进行构建。
这时候,我们需要的目标文件 HelloWorld
已经构建完成,位于当前目录,尝试运行一下:
./HelloWorld
得到输出:
Hello,World!
三.基本用法解释
上面用一个非常简单的HelloWorld例子简单介绍了构建使用cmake构建项目的完整过程.但是其中还有很多地方新手可能不是很理解.比如CMake怎么使用. CMakeList.txt
里面到底是一些什么东西等等. 这部分就来讲一下上面那个简单的项目到底用了一些什么东西.更加复杂的以后再讲到,这里确保把最基本的一些给理清楚.
重新看一下 CMakeLists.txt
,这个文件是 cmake 的构建定义文件,文件名
是大小写相关的,如果工程存在多个目录,需要确保每个要管理的目录都存在一个
CMakeLists.txt。(关于多目录构建,后面我们会提到,这里不作过多解释)。
上面例子中的 CMakeLists.txt 文件内容如下:
cmake_minimum_required(VERSION 3.9)
project(HelloWorld)
set(CMAKE_CXX_STANDARD 11)
add_executable(HelloWorld main.cpp)
先看第一行cmake_minimum_required(VERSION 3.9)
,这行看意思都能够直接看出来了,表示指定运行此配置文件所需的 CMake 的最低版本;所以看到其他的CMakeList文件没有写这个也是正常的.但是还是推荐写,是因为避免引起cmake不同版本之间构建错误的问题.
然后看第二行,project(HelloWorld)
该命令指定项目的名称,比如这里的项目名称为HelloWorld.更加详细的来说, project 指令的语法是:
project(projectname [CXX] [C] [Java])
你可以用这个指令定义工程名称,并可指定工程支持的语言,支持的语言列表是可以忽略的,
默认情况表示支持所有语言。所以我们常见使用的时候,就直接使用project(projectname)
就够了. 这个指令隐式的定义了两个 cmake 变量:
_BINARY_DIR 以及_SOURCE_DIR,这里就是
HelloWorld_BINARY_DIR
和 HelloWorld_SOURCE_DIR
.
因为采用的是内部编译,两个变量目前指的都是工程所在路径LearningCMake/HelloWorld/,后面我们会讲到外部编译,两者所指代的内容会有所不同。
同时 cmake 系统也帮助我们预定义了 PROJECT_BINARY_DIR
和 PROJECT_SOURCE_DIR
变量,他们的值分别跟 HelloWorld_BINARY_DIR
与 HelloWorld_SOURCE_DIR
一致。 为了统一起见,建议以后直接使用 PROJECT_BINARY_DIR
,PROJECT_SOURCE_DIR
,即
使修改了工程名称,也不会影响这两个变量。如果使用了
<projectname>_SOURCE_DIR
,修改工程名称后,需要同时修改这些变量。
然后来看第三行set(CMAKE_CXX_STANDARD 11)
这里是把之后的编译选项设置为了C++ 11,
set 指令的语法是:
set (VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]])
现阶段,你只需要了解 set 指令可以用来显式的定义变量即可。
比如我们用到的是 set(SRC_LIST main.c)
,如果有多个源文件,也可以定义成:
set(SRC_LIST main.c t1.c t2.c)
。
然后我们来看最后一行add_executable(HelloWorld main.cpp)
,这行的作用就是将名为 main.cpp
的源文件编译成一个名称为 HelloWorld
的可执行文件。同样的,更加详细的用法如下:
add_executable(executable_name $SRC_LIST)
定义了这个工程会生成一个文件名为 executable_name
的可执行文件,相关的源文件是 SRC_LIST
中
定义的源文件列表.
四.内部构建和外部构建
内部构建和外部构建这个词这么装逼,其实实际上面非常简单,别被吓到.
通俗一点,内部构建就是在项目内部,有CMakeList.txt
的地方,直接cmake .
,比如我们前面讲的简单案例都是最简单的内部构建. 结果你也看见了,就是在项目下面生成了很多的临时文件.
外部构建就是不直接在项目下面运行cmake
, 而是自己建立一个接受cmake之后的临时文件的文件夹,然后再该文件夹下面调用cmake <CMakeList_path>
来构建.运行 make 构建工程,就会在当前目录(build 目录)中获得目标文件 hello。上述过程就是所谓的out-of-source外部编译,一个最大的好处是,对于原有的工程没有任何影响,所有动作全部发生在编译目录。
有编译过OpenCV或者其他类似项目的童鞋,都应该知道,编译OpenCV的时候,我们常常自己建立一个build目录,然后在该目录下面运行cmake,最终临时文件就会在这个目录下面生成.
这里直接举一个例子,完整项目代码:LearningCMake/4.HelloWorld4/
这里代码结构和CMakeList.txt都和第一个最简单的是差不多的.但是这里有一个不同,就是在里面建立了一个build文件夹.然后再build文件夹里面运行cmake ..
,结果就是之前的临时文件都存放在了这个build文件夹里面,同时在这个文件夹里面直接make可以得到最终的可执行文件.
到了这里,结合CMakeList.txt文件中每个命令语句和生成执行文件的详细步骤.你应该对于cmake的运作过程有了一个基本的了解.当然这并不等于全部,有了这些基础,后面慢慢介绍更多更加常用的用法.
以上是关于CMake入门实践 什么是cmake的主要内容,如果未能解决你的问题,请参考以下文章