1.CMake的简介

  • CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程)。他能够输出各种各样的makefile或者project文件
  • CMake主要是编写CMakeLists.txt文件,然后用cmake命令将CMakeLists.txt文件转化为make所需要的makefile文件,最后用make命令编译源码生成可执行程序

    2.CMake的编译小技巧

  • cmake 指向CMakeLists.txt所在的目录,例如cmake .. 表示CMakeLists.txt在当前目录的上一级目录。cmake后会生成很多编译的中间文件以及makefile文件,所以一般建议新建一个新的目录,专门用来编译
    1
    2
    3
    4
    mkdir build     建立一个新的文件夹专门存放中间的编译文件
    cd build 进入这个文件目录
    cmake .. 必须在有CMakeLists.txt所在的目录下cmake
    make 最后编译生成可执行程序

    3.CMake语法

  • 变量使用${}方式取值,但是在 IF 控制语句中是直接使用变量名;
  • 指令(参数 1 参数 2…),参数使用括弧括起,参数之间使用空格或分号分开;
  • 指令是大小写无关的,参数和变量是大小写相关的。推荐全部使用大写指令。

    4.编写一个C程序理解整个CMake过程

    文件目录结构如下:

wd.h

1
2
3
4
5
#ifndef WD_TEST
#define WD_TEST
#include<math.h>
double wd_sqrt(double value);
#endif

wd.c
1
2
3
4
5
#include "../include/wd.h"
double wd_sqrt(double value)
{
return sqrt(value);
}

main.c
1
2
3
4
5
6
7
8
9
10
11
12
#include "../include/wd.h"
#include <stdio.h>
int main(int argc, char** argv)
{
double a = 0.0;
double b = 0.0;
printf("please input a number:\n");
scanf("%lf",&a);
b = wd_sqrt(a);
printf("sqrt result:%f\n",b);
return 0;
}

5.CMake常用命令

1. cmake_minimum_required(VERSION 3.4.1)

  • 规定cmake程序的最低版本。这行命令是可选的,我们可以不写这句话,但在有些情况下,如果CMakeLists.txt文件中使用了一些高版本cmake特有的一些命令的时候,就需要加上这样一行,提醒用户升级到该版本之后再执行cmake。

2. project( < projectname> [languageName1 languageName2 … ] )

  • 为本工程设置一个工程名,一般与文件名相对应。后面的可选项还可以让你指定你的工程可以支持的语言。比如CXX(即C++),C等等。在默认条件下,支持C和C++语言。

3. include_directories()

  • CMake中,添加头文件路径,对应的函数叫include_directories。然后在参数中,把所有需要添加的路径,加进去就可以了。

4.aux_source_directory(< dir > < variable >)

  • 搜集所有在指定路径下的源文件的文件名,将输出结果列表储存在指定的变量中。

5. set()

  • 经常配合set命令使用的CMake变量,使用set(variable value)进行设置。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    # 设置可执行文件的输出路径(EXCUTABLE_OUTPUT_PATH是全局变量)
    set(EXECUTABLE_OUTPUT_PATH [output_path])
    # 设置库文件的输出路径(LIBRARY_OUTPUT_PATH是全局变量)
    set(LIBRARY_OUTPUT_PATH [output_path])
    # 设置C++编译参数(CMAKE_CXX_FLAGS是全局变量)
    set(CMAKE_CXX_FLAGS "-Wall std=c++11")
    # 设置源文件集合(SOURCE_FILES是本地变量即自定义变量)
    set(SOURCE_FILES main.cpp test.cpp ...)
    #set命令还可以设置自定义变量,比如
    set(MY_GREETINGS "hello world")
    #设置环境变量,编译用到的源文件全部都要放到这里
    set(WD_MATH ${DIR_SRCS)

6. add_executable(<可执行文件名字> <源文件列表>)

1
2
#使用SRC_LIST源文件列表里的文件生成一个可执行文件hello
add_executable(hello ${SRC_LIST})

7. add_library(< name> [STATIC | SHARED | MODULE | UNKNOWN] IMPORTED)

  • 导入一个库,STATIC, SHARED, MODULE参数来指定要创建的库的类型, STATIC对应的静态库(.a),SHARED对应共享动态库(.so)
  • 导入了一个已存在的库文件,导入库一般配合set_target_properties使用,这个命令用来指定导入库的路径,比如:
    1
    2
    3
    4
    5
    add_library(test SHARED IMPORTED) 
    set_target_properties(
    test #指定目标库名称
    PROPERTIES IMPORTED_LOCATION #指明要设置的参数 libs/src/${ANDROID_ABI}/libtest.so
    #设定导入库的路径)

8. target_link_libraries(<目标文件><库文件>)

  • 该指令的作用为将目标文件与库文件进行链接.

9. find_package()

  • 查找并加载外来工程的设置
    1
    2
    3
    4
    find_package(<package> [version] [EXACT] [QUIET]
    [[REQUIRED|COMPONENTS] [components...]]
    [NO_POLICY_SCOPE])
    查找并加载外来工程的设置。该命令会设置<package>_FOUND变量,用来指示要找的包是否被找到了。如果这个包被找到了,与它相关的信息可以通过包自身记载的变量中得到。QUIET选项将会禁掉包没有被发现时的警告信息。REQUIRED选项表示如果报没有找到的话,cmake的过程会终止,并输出警告信息。

10. if命令

1
2
3
4
5
if(${CMAKE_BUILD_TYPE} MATCHES "debug")
...
else()
...
endif()

11.list命令

1
2
3
4
5
6
7
list(APPEND SRC_LIST 
a.cpp
b.cpp
)
list(REMOVE_ITEM SRC_LIST
a.cpp
)

6.编写CMakeLists.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#指定cmake版本 
cmake_minimum_required(VERSION 3.2)
#指定项目的名称,一般和项目的文件夹名称对应
PROJECT(wd)
#头文件目录
INCLUDE_DIRECTORIES(
include
)
#源文件目录
AUX_SOURCE_DIRECTORY(src DIR_SRCS)
#设置环境变量,编译用到的源文件全部都要放到这里
SET(WD_MATH
${DIR_SRCS}
)
#添加要编译的可执行文件
ADD_EXECUTABLE(${PROJECT_NAME} ${WD_MATH})

TARGET_LINK_LIBRARIES(${PROJECT_NAME} m)
  • 这样cmake .. 之后就生成了一个makefile文件,再make就生成了一个可执行程序。