CMake

CMake编译过程

  • 创建CMakeLists.txt文件:touch CMakeLists.txt
  • 使⽤cmake,生成makefile文件
  • 使⽤make命令编译,生成了可执行程序

PROJECT

PROJECT:来指定工程的名称

1
PROJECT (HELLO)

add_executable:定义工程会生成一个可执行程序

1
add_executable(可执行程序名 源文件名称)

SET

  • 显示地指定变量

    SET(SRC_LIST main.cpp) SRC_LIST变量就包含了main.cpp

    多个cpp文件:SET(SRC_LIST main.cpp t1.cpp t2.cpp)

  • 在 CMakeLists.txt 中通过 set 命令指定所使用的C++标准:

    1
    2
    3
    4
    5
    6
    #增加-std=c++11
    set(CMAKE_CXX_STANDARD 11)
    #增加-std=c++14
    set(CMAKE_CXX_STANDARD 14)
    #增加-std=c++17
    set(CMAKE_CXX_STANDARD 17)
  • 指定输出的路径:

    1
    2
    set(HOME /home/robin/Linux/Sort)
    set(EXECUTABLE_OUTPUT_PATH ${HOME}/bin)

    注:EXECUTABLE_OUTPUT_PATH是可执行程序输出的路径对应的宏,如果这个路径中的子目录不存在,会自动生成,无需自己手动创建

搜索文件

  • aux_source_directory 命令可以查找某个路径下的所有源文件

    1
    2
    3
    4
    5
    6
    cmake_minimum_required(VERSION 3.0)
    project(CALC)
    include_directories(${PROJECT_SOURCE_DIR}/include)
    # 搜索 src 目录下的源文件
    aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src SRC_LIST)
    add_executable(app ${SRC_LIST})

注1:PROJECT_SOURCE_DIR是执行cmake命令时指定的路径; CMAKE_CURRENT_SOURCE_DIR是当前的CMakeLists.txt所对应的路径

注2:PROJECT_SOURCE_DIRCMAKE_CURRENT_SOURCE_DIR存储的值是一样的

  • file(GLOB/GLOB_RECURSE 变量名 要搜索的文件路径和文件类型)

    • GLOB: 将指定目录下搜索到的满足条件的所有文件名生成一个列表,并将其存储到变量中。

    • GLOB_RECURSE:递归搜索指定目录,将搜索到的满足条件的文件名生成一个列表,并将其存储到变量中。

      1
      2
      file(GLOB MAIN_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)
      file(GLOB MAIN_HEAD ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h)
  • include_directories: 用于指定头文件的路径

制作动态库和静态库

  • 制作静态库:add_library(<库名称> STATIC <源文件>)

注1:在Linux中,静态库名分为三部分:lib+库名称+.a

  • 制作动态库:add_library(<库名称> SHARE <源文件>)

  • 使用LIBRARY_OUTPUT_PATH指定生成的库文件的路径

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    cmake_minimum_required(VERSION 3.0)
    project(CALC)
    include_directories(${PROJECT_SOURCE_DIR}/include)
    file(GLOB SRC_LIST "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
    # 设置动态库/静态库生成路径
    set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
    # 生成动态库
    #add_library(calc SHARED ${SRC_LIST})
    # 生成静态库
    add_library(calc STATIC ${SRC_LIST})
  • 链接静态库:link_libraries(<库名称>...)

    注:如果静态库是自定义的,要使用link_directories(<lib path>)来指定库路径

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    cmake_minimum_required(VERSION 3.0)
    project(CALC)
    # 搜索指定目录下源文件
    file(GLOB SRC_LIST ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)
    # 包含头文件路径
    include_directories(${PROJECT_SOURCE_DIR}/include)
    # 包含静态库路径
    link_directories(${PROJECT_SOURCE_DIR}/lib)
    # 链接静态库
    link_libraries(calc)
    add_executable(app ${SRC_LIST})
  • 链接动态库:

    1
    2
    3
    4
    target_link_libraries(
    <需要链接动态库的文件>
    <PRIVATE|PUBLIC|INTERFACE> <库名称>...
    [<PRIVATE|PUBLIC|INTERFACE> <库名称>...]...)

    注:默认权限为PUBLIC,PUBLIC具有传递性; INTERFACE只会导出符号

    1
    2
    3
    4
    5
    6
    7
    cmake_minimum_required(VERSION 3.0)
    project(TEST)
    file(GLOB SRC_LIST ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
    # 添加并指定最终生成的可执行程序名
    add_executable(app ${SRC_LIST})
    # 指定可执行程序要链接的动态库名字
    target_link_libraries(app pthread)

日志信息

1
message([STATUS|WARNING|AUTHOR_WARNING|FATAL_ERROR|SEND_ERROR] "message to display" ...)
  • (无) :重要消息
  • STATUS:非重要消息
  • WARNING:CMake 警告, 会继续执行
  • AUTHOR_WARNING:CMake 警告 (dev), 会继续执行
  • SEND_ERROR:CMake 错误, 继续执行,但是会跳过生成的步骤
  • FATAL_ERROR:CMake 错误, 终止所有处理过程

变量的操作

  • 字符串拼接:

    • set(变量名1 ${变量名1} ${变量名2} ...)

    • list(APPEND <list> [<element> ...])

      1
      2
      3
      4
      5
      6
      7
      cmake_minimum_required(VERSION 3.0)
      project(TEST)
      set(TEMP "hello,world")
      file(GLOB SRC_1 ${PROJECT_SOURCE_DIR}/src1/*.cpp)
      file(GLOB SRC_2 ${PROJECT_SOURCE_DIR}/src2/*.cpp)
      # 追加(拼接)
      list(APPEND SRC_1 ${SRC_1} ${SRC_2} ${TEMP})
  • 字符串移除:

    list(REMOVE_ITEM <list> <value> [<value> ...])

    1
    2
    3
    file(GLOB SRC_1 ${PROJECT_SOURCE_DIR}/*.cpp)
    # 移除 main.cpp
    list(REMOVE_ITEM SRC_1 ${PROJECT_SOURCE_DIR}/main.cpp)

定义宏

add_definitions(-D宏名称)

1
2
3
4
5
cmake_minimum_required(VERSION 3.0)
project(TEST)
# 自定义 DEBUG 宏
add_definitions(-DDEBUG)
add_executable(app ./test.c)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#define NUMBER 3

int main()
{
int a = 10;
#ifdef DEBUG
printf("我是一个程序猿, 我不会爬树...\n");
#endif
for(int i=0; i<NUMBER; ++i)
{
printf("hello, GCC!!!\n");
}
return 0;
}

嵌套的CMake

建立父子节点之间的关系:

1
add_subdirectory(source_dir)

source_dir: 子节点所在的目录

注:子节点可以使用根节点定义的变量,而根节点不可以使用子节点的变量