cmake的使用以及语法

前言

我们使用 Make 工具构建项目时,需要编写 Makefile,但不同的平台 Make工具是不一样的,比如LinuxGNU MakeWindowsnmake,它们对 Makefile的规范也是不一样的,如果软件要跨平台,则需要针对每一种 Make工具写一份 Makefile,非常浪费时间

而且当软件比较庞大时,Makefile的编写也会变的复杂。

CMake 简介

CMake(Cross-Platform-Make)是一个开源、跨平台的软件构建工具,它使用与平台独立的配置文件来对软件编译过程进行控制,根据用户所需,生成 Makefile 或者IDEproject。

CMake 构建过程

  1. 编写CMake 配置文件CMakeLists.txt,一般放在项目的最顶层目录下

  2. 运行 cmake 命令,参数为 CMakeLists.txt 所在根路径,执行完成后得到 Makefile 文件。

  3. 使用make 命令进行编译。

    1
    2
    3
    mkdir -p build && cd build
    cmake ..
    make

cmake基本语法

  1. 指定最小版本

    如果使用的 CMake版本低于该版本,则会发出致命错误

    1
    cmake_minimum_required(VERSION 3.9)
  2. 设置工程名 可以同时指定工程版本和语言,CXX代表C++

    1
    project(sunflower VERSION 0.0.1 LANGUAGES C CXX)
  3. 单行注释

    1
    # 我是注释
  4. 多行注释

    1
    2
    3
    #[[我是多行注释
    我是多行注释
    ]]
  5. 设置 c/c++版本

    1
    2
    set(CMAKE_C_STANDARD 11)
    set(CMAKE_CXX_STANDARD 11)
  6. 设置编译选项

    1
    2
    set(CMAKE_C_FLAGS   "${CMAKE_C_FLAGS} -g -w -O3")
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -w -O3")
  7. 添加宏定义

    1
    add_definitions(-DSPDLOG_ACTIVE_LEVEL=SPDLOG_LEVEL_INFO)
  8. 设置头文件搜索目录

    实现编译时的 [-I] 选项,设置后引用头文件不需要使用相对路径,直接引用文件名

    1
    2
    3
    4
    5
    include_directories(
    "${PROJECT_SOURCE_DIR}/include"
    "${PROJECT_SOURCE_DIR}/depends/json/"
    "${PROJECT_SOURCE_DIR}/depends/leveldb/include"
    )
  9. 设置库文件搜索目录

    实现编译时的[-L]选项,项目内部明确路径的库文件,可以通过该命令指定

    1
    2
    3
    4
    link_directories(
    "${PROJECT_SOURCE_DIR}/depends/json/lib"
    "${PROJECT_SOURCE_DIR}/depends/leveldb"
    )
  10. 查找指定库文件

    查找到指定的预编译库,并将它的路径存储在变量中。

    默认的搜索路径为 cmake 包含的系统库,因此如果是NDK的公共库只需要指定库的name 即可(不需path),类似的命令还有find_file()find_path()find_program()find_package()

    1
    find_library(log-lib,log)
  11. 查找指定目录下源文件
    获取指定目录下源文件列表,保存到 DIR_SRCS 变量中,后续编译构建目标可执行文件

    注意这里不能递归获取子目录下的源文件

    1
    aux_source_directory(${PROJECT_SOURCE_DIR}/src DIR_SRCS)
  12. 添加子目录源文件
    使用命令 add_subdirectory 指明本项目包含一个子目录,这样子目录下的 CMakeLists.txt文件和源文件也会被处理。

    项目包含多个子目录时,通常可以在子目录下也定义CMakeLists.txt 文件,并通过 add_library 生成包含子目录源码的库文件,并最终链接到目标可执行文件

    1
    2
    add_subdirectory(utils)
    add_subdirectory(config)
  13. 递归查找目录下的所有源文件
    可以通过 file命令递归获取指定目录下的所有源文件,这样可以不用为子目录专门定义CMakeLists.txt,也不需要通过链接的方式集成各个子目录,而是统一编译构建

    1
    2
    3
    4
    5
    file(GLOB_RECURSE DIR_SRCS
    ${PROJECT_SOURCE_DIR}/src/*.c
    ${PROJECT_SOURCE_DIR}/src/*.cc
    ${PROJECT_SOURCE_DIR}/src/*.cpp
    )
  14. 设置可执行文件输出路径

    1
    set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
  15. 生成可执行文件

    1
    add_executable(${PROJECT_NAME} ${DIR_SRCS})
  16. 生成库文件

    1
    2
    add_library(${PROJECT_NAME} STATIC ${DIR_SRCS})
    add_library(${PROJECT_NAME} SHARED ${DIR_SRCS})
  17. 链接库文件

    1
    2
    3
    4
    5
    6
    7
    set(EXTRA_LIBS
    sasl2
    libleveldb.a
    )
    target_link_libraries(${PROJECT_NAME}
    ${EXTRA_LIBS}
    )

常用变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
PROJECT_SOURCE_DIR:工程的根目录

PROJECT_BINARY_DIR:运行cmake命令的目录,通常为${PROJECT_SOURCE_DIR}/build

PROJECT_NAME:返回通过 project 命令定义的项目名称

CMAKE_CURRENT_SOURCE_DIR:当前处理的 CMakeLists.txt 所在的路径

CMAKE_CURRENT_BINARY_DIR:target 编译目录

CMAKE_CURRENT_LIST_DIR:CMakeLists.txt 的完整路径

EXECUTABLE_OUTPUT_PATH:重新定义目标二进制可执行文件的存放位置

LIBRARY_OUTPUT_PATH:重新定义目标链接库文件的存放位置

自定义变量

使用SET, 比如:

1
2
3
4
5
6
7
8
set(BINARY_NAME "juce_jni")

add_library( ${BINARY_NAME}

SHARED

"../../../Source/Main.cpp"
)

支持 Debug 版本

  1. 设置不同版本的编译选项

    1
    2
    set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb")
    set(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall")
  2. cmake 时指定版本

    1
    2
    cmake .. -DCMAKE_BUILD_TYPE=Debug
    cmake .. -DCMAKE_BUILD_TYPE=Release

完整示例

工程结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
+-- CMakeTest
|
+-- CMakeList.txt
+-- src
|
+-- main.cc
+--- utils/
|
+--- utils.cc
+--- utils.h
+-- config/
|
+-- config.cc
+-- config.h
+-- libs
|
+-- libleveldb.a

CMakeList.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
cmake_minimum_required(VERSION 3.7.1)

project(CMakeTest VERSION 0.0.1 LANGUAGES C CXX)

set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 11)

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -w -O3")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -w -O3")

set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)

include_directories(
"utils"
"config"
)

link_directories(
""${PROJECT_SOURCE_DIR}/libs""
)

# 子目录的CMakeList.txt也可以定义到主配置中
# 将utils和config两个子目录的源文件打包成库test_share
aux_source_directory(${PROJECT_SOURCE_DIR}/src/utils SHARE_SRC_FILES)
aux_source_directory(${PROJECT_SOURCE_DIR}/src/config SHARE_SRC_FILES)
add_library(test_share STATIC ${SHARE_SRC_FILES} )

aux_source_directory(${PROJECT_SOURCE_DIR}/src DIR_SRCS)
add_executable(${PROJECT_NAME} ${DIR_SRCS})

# 也可以使用file命令递归获取目录下所有源文件
file(GLOB_RECURSE DIR_SRCS
${PROJECT_SOURCE_DIR}/src/*.c
${PROJECT_SOURCE_DIR}/src/*.cc
${PROJECT_SOURCE_DIR}/src/*.cpp
)
add_executable(${PROJECT_NAME} ${DIR_SRCS})

set(EXTRA_LIBS
ldl
pthread
libleveldb.a
)

target_link_libraries(${PROJECT_NAME}
test_share
${EXTRA_LIBS}

)

本文转载自: CSDN

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

0%