了解
cmake是cross platform make的缩写,用于跨平台的工程构建和编译。它在make基础上,使用比make更加简单的语法来构建软件工程。cmake能感知系统和平台,生成不同的工程文件,比如unix的Makefile,Windows的sln或者苹果系统的XCode工程。
在Linux系统,比起手写Makefile来,cmake也是简单一些,目前很多开源软件都提供了cmake脚本来构建项目。在Linux下,cmake的功能是根据脚本,生成Makefile文件,用于构建。
熟悉
1.环境搭建
Ubuntu系统,通过以下命令安装cmake
sudo apt-get install cmake
2.HelloWorld
先来一个最简单的例子,打开终端,输入以下命令:
mkdir HelloWorld
cd HelloWorld
touch CMakeLists.txt
touch main.c
编辑main.c和CMakeLists.txt
main.c内容如下:
include <stdio.h>
int main()
{
printf("hello world\n");
return 0;
}
CMakeLists.txt内容如下
project(HelloWorld)
add_executable(HelloWorld.bin main.c)
在HelloWorld目录下,执行以下命令:
mkdir build
cd build
cmake ..
make
编译后会产生一个HelloWorld.bin,执行它会输出HelloWorld
3.HelloWorld的解释
HelloWorld工程的CMakeLists.txt非常简单,简要介绍以下
#指定工程名称为HelloWorld
project(HelloWorld)
#用main.c编译HelloWorld.bin
add_executable(HelloWorld.bin main.c)
命令的解释:
mkdir build
由于cmake在编译时产生很多中间文件,为了隔离中间文件和源代码,一般会创建一个目录来存放中间文件,一般目录名字为build,这个是可选的,但是大家都这么做。
cd build
cmake ..
进入到中间目录,执行cmake命令,cmake命令的参数..表示CMakeLists.txt在上层目录,cmake命令会生成Makefile,同时做一些必要的环境检查。
make
编译
掌握
恭喜你,到这里时,你已经学会如何使用cmake来构建应用程序了。但是还不够的是,还是有许多的问题没有解决。
2.1 使用变量
使用变量能够使代码变得有可读性和可维护性,通过set指令,来定义变量,通过${}来引用变量。以上的CMakeLists.txt,也可以改成这样子:
project(HelloWorld)
set(src main.c)
add_executable(HelloWorld.bin ${src})
set(src main.c)表示定义一个变量src,让它等于main.c。如果一个工程有多个文件,那么可以写成这样子:
project(HelloWorld)
set(src main.c func.c foo.c)
add_executable(HelloWorld.bin ${src})
2.2 搜索目录
如果目录下有100个文件,10000个文件,这么写超级累,还是用大招吧。aux_source_directory可以将目录中的所有源码,加入到工程。
cmake_minimum_required(VERSION 3.7)
project(HelloWorld)
#set(src main.c foo.c func.c)
aux_source_directory(. src)
add_executable(HelloWorld.bin ${src})
注意上面的代码,set指令已经被注释了,取而代之的是aux_source_directory指令。
要注意的是,aux_source_directory这个指令,不会递归的搜索子目录,如果有子目录的代码也要加入,比如该目录下有一个sub目录,那么应该这样写:
cmake_minimum_required(VERSION 3.7)
project(HelloWorld)
#set(src main.c foo.c func.c)
aux_source_directory(. src)
aux_source_directory(./sub src)
add_executable(HelloWorld.bin ${src})
注意,从这里开始多了一行cmake_minimum_required(VERSION 3.7),这个表示要求用户的cmake版本是3.7以上
以后把代码写到一个目录,然后xxx就完事儿了,貌似是比make方便一些。
2.3 链接动态库
如果代码用了pthread_create,要链接一个动态库怎么办?不用着急,对cmake来说,是小意思。使用target_link_libraries,让最终目标链上动态库即可。不过要注意的是,target_link_libraries指令要放在add_executable指令之后。例子如下:
cmake_minimum_required(VERSION 3.7)
project(HelloWorld)
#set(src main.c foo.c func.c)
aux_source_directory(. src)
aux_source_directory(./sub src)
add_executable(HelloWorld.bin ${src})
target_link_libraries(HelloWorld.bin pthread)
上面的例子,HelloWorld.bin用了两次,这意味着将来如果要修改,那么可能会修改多次,可以使用变量优化一下。
cmake_minimum_required(VERSION 3.7)
project(HelloWorld)
set(target HelloWorld.bin)
aux_source_directory(. src)
aux_source_directory(./sub src)
add_executable(${target} ${src})
target_link_libraries(${target} pthread)
2.4 设置头文件目录和库目录
2.4.1 设置头文件目录
有时候需要链接第三方库,以及要包含第三方的头文件,cmake那么强大,这个自然也是小意思的,用include_directories就可以了,它可以同时指定多个目录。下面的代码没测试过,我就那么一写,读者可以去测试一下效果。
cmake_minimum_required(VERSION 3.7)
project(HelloWorld)
set(target HelloWorld.bin)
set(opencv_include /home/xueguoliang/opencv/include)
set(libevent_include /home/xueguoliang/libevent/include)
include_directories(${opencv_include} ${libevent_include})
aux_source_directory(. src)
aux_source_directory(./sub src)
add_executable(${target} ${src})
target_link_libraries(${target} pthread)
2.4.2 设置库目录
使用link_directories来设置库目录。比如
link_directories(/home/xueguoliang/opencv/lib /home/xueguoliang/libevent/lib)
2.5 编译目标是一个动态库或者静态库
add_library
set_target_properties
2.6 定义宏
可以通过指令add_definitions(-DFOO -DBAR …),也可以在命令时通过cmake -DFOO来增加,也可以让cmake内置变量,是什么来着,忘记了,以上两种也够用了啊。
所有内置变量:https://cmake.org/cmake/help/v3.0/manual/cmake-variables.7.html
2.7 设置编译选项
听说不支持CPPFLAGS,支持CFLAGS,CXXFLAGS,但是不支持CPPFLAGS
2.8 条件编译和函数
这个是另外一个课题了,先看看这个文章,有用到时再去学学,知道有这个东西即可。
http://blog.chinaunix.net/uid-24512513-id-3196376.html