cmake使用

1.创建 CMakeLists.txt 文件并进行编辑

2.使用 cmake \ . 命令,. 指的是当前文件夹,生成 Makefile 文件

3.使用 make 命令生成可执行文件

CMakeLists.txt 语法

版本

cmake_minimum_required(VERSION 3.10)**

指定最低 cmake 版本

PROJECT 关键字

用来指定工程的名字和支持的语言

PROJECT(HELLO)​ 工程名为 ​HELLO​,默认支持所有语言

PROJECT(HELLO CXX)​ 工程名为 ​HELLO​,支持语言 CXX

PROJECT(HELLO CXX C JAVA)​ 多种语言用空格或分号隔开

该指定隐式定义了两个 CMAKE 变量

_BINARY_DIR,比如 HELLO _BINARY_DIR,也可以直接简化使用 PROJECT _BINARY_DIR 来表示,这是编译路径

_SOURCE_DIR,比如 HELLO _SOURCE_DIR,也可以直接简化使用 PROJECT _SOURCE_DIR 来表示,这是工程路径

在 MESSAGE 关键字中可以直接使用这两个变量,指向当前的工作目录

SET 关键字

用来指定变量,默认都是字符串类型

SET(SRC_LIST main.cpp)​ 其中​ SRC_LIST ​变量包含 ​main.cpp​

SET(SRC_LIST a.cpp b.cpp c.cpp)​

SET(CMAKE_CXX_STANDARD 11) 指定c++版本为 11,CMAKE_CXX_STANDARD是宏不是变量

MESSAGE 关键字

用来在终端输出信息

主要包含三种信息:

  • SEND_ERROR​,产生错误,生成过程被跳过
  • STAUS,输出前缀为 – 的信息
  • FATAL_ERROR ,立即终止所有 cmake 过程

ADD_EXECUTABLE 关键字

生成可执行文件

ADD_EXECUTABLE(hello\ \{SRC_LIST}) 生成的可执行文件名为 hello ,源文件读取变量 SRC_LIST 中的内容

也可以直接写成 ADD_EXECUTABLE(hello\ \{SRC_LIST})

文件搜索

file(GLOB/GLOB_RECURSE 变量名 文件路径和类型)

第一个参数指定如何搜索,GLOB表示当前文件下搜索,GLOB_RECURSE表示递归搜索

例:file(GLOB MAIN_SRC /src/*.cpp)

指定头文件路径

INCLUDE_DIRECTORIES(path)

path 为头文件路径

宏定义

add_definitions(-D宏名称 …)

add_definitions(-D宏名称=100) 使用 = 来进行宏的初始化

内部构建和外部构建

内部构建:直接构建,因为文件多导致不整洁

外部构建:在 CMakeFile.txt 所在目录创建一个 build 文件夹,在 build 目录下使用 cmake \ … 命令,构建后的文件都会放在 build 文件夹下,此时编译路径为 ./build 而工程路径为 build 所在路径

规范

  • 添加一个子目录 src ,用来放置工程源代码
  • 添加一个子目录 doc,用来放置工程文档
  • 工程目录下添加 runhello.sh,运行二进制文件的脚本
  • 工程目录下添加文本文件 COPYRIGHT,README
  • 将构建后的目标文件放入构建目录的 bin 子目录

工程目录

.
├── build
├── CMakeLists.txt
└── src
    ├── CMakeLists.txt
    └── main.cpp

工程目录下的 CMakeLists.txt

PROJECT(HELLO)
ADD_SUBDIRECTORY(src bin)

src 下的 CMakeLists.txt

ADD_EXECUTABLE(hello main.cpp)

ADD_SUBDIRECTORY

ADD_SUBDIRECTORY(source_dir [binary_dir] [EXCLUDE_FROM_ALL])

  • 这个指令用于想当前工程添加存放源文件的子目录,并可以指定二进制文件存放位置。ADD_SUBDIRECTORY(src bin) 生成的二进制文件在 /build/bin下,ADD_SUBDIRECTORY(src)生成的二进制文件在 /build/src 下
  • EXCLUDE_FROM_ALL 函数禁止该子目录下的目标被默认构建,和直接不写ADD_SUBDIRECTORY效果相同

静态库和动态库的构建

静态库文件后缀 .a,windows下是 .lib

动态库文件后缀 .so,windows下是 .dll

指定头文件路径

include_directories(path)

生成库

ADD_LIBRARY(库名称 STATIC 源文件)

ADD_LIBRARY(库名称 SHARE 源文件)

指定生成路径

SET(LIBRARY_OUTPUT_PATH path)

全局链接库

link_libraries(库1 库2 …)

后续所有目标都会链接这些库

指定库路径

link_directories(path1 path2 …)

系统的库只需要名字就可以找到

自定义的库则还需要指定路径

指定链接库

target_link_libraries(target 权限1 库1 权限2 库2…)

target 指定要加载库的文件名,可以为源文件、动态库文件、可执行文件。

权限:PRIVATE、PUBLIC、INTERFACE

默认权限是 PUBLIC

target_link_libraries(B 权限 C)

target_link_libraries(A B)

若权限为 PUBLIC,则 A 中能调用 C 中的函数

若权限为 PRIVETE,则 A 中不能调用 C 中的函数

target_link_libraries(B 权限 C 权限 D)

target_link_libraries(A B)

若权限为 INTERFACE,则 A 中不能调用 C、D中的函数,B 中可以调用但不知道函数来自于 C 还是 D。也就是说 C、D不会被链接到 B,只会导出符号(符号就是函数)。


不积跬步,无以至千里!