CMake总结

本文详细介绍了CMake的基本使用,包括设置最低版本,创建项目,添加可执行文件,指定输出路径,设置C++标准,搜索源文件,以及制作和使用静态库和动态库的过程。还探讨了如何在嵌套目录结构中管理和配置CMakeLists.txt。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Cmake使用

  • 注释使用#
  • 多行注释使用#[[注释内容]]

常用内容

cmake_minimum_required(VERSION 3.0)#设置最低版本
project(CALC)                      #设置项目名称
#[[add_executable(可执行程序名 源文件名称)]]
add_executable(app add.c div.c main.c mult.c sub.c) #定义工程生成的可执行文件

#指定可执行程序的输出的路径
set(HOME /home/robin/Linux/Sort)
set(EXECUTABLE_OUTPUT_PATH ${HOME}/bin)

# 设置c++标准
#增加-std=c++11
set(CMAKE_CXX_STANDARD 11)


#搜索源文件,存储到变量中
#法一
#[aux_source_directory(路径  变量名)
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src SRC_LIST)
# [搭配使用:add_executable(app  ${SRC_LIST})
#法二
file(GLOB MAIN_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)
file(GLOB_RECURSE MAIN_HEAD ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h)
#GLOB搜索 GLOB_RECURSE递归搜索

#设置头文件路径
include_directories(headpath)
  • 使用cmake执行CMakeLists.txt 中的内容,通常在CMakeLists.txt的同级目录下新建build文件夹,执行cmake …,这样可以将cmake生成的中间文件放在build文件夹中。
举例子

目录结构:

$ tree
.
├── build
├── CMakeLists.txt
├── include
│   └── head.h
└── src
    ├── add.cpp
    ├── div.cpp
    ├── main.cpp
    ├── mult.cpp
    └── sub.cpp

3 directories, 7 files
cmake_minimum_required(VERSION 3.0)
project(CALC)
set(CMAKE_CXX_STANDARD 11)
set(HOME /home/robin/Linux/calc)
set(EXECUTABLE_OUTPUT_PATH ${HOME}/bin/)
# PROJECT_SOURCE_DIR是cmake后面跟的路径
include_directories(${PROJECT_SOURCE_DIR}/include)
file(GLOB SRC_LIST ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)
add_executable(app  ${SRC_LIST})

定义变量

  • 通过set设置变量
# SET 指令的语法是:
# [] 中的参数为可选项, 如不需要可以不写
SET(变量名 [变量值] [CACHE TYPE DOCSTRING [FORCE]])
  • 变量值中涉及多个文件可以通过空格或;分割

set(SRC_LIST add.c;div.c;main.c;mult.c;sub.c)
add_executable(app  ${SRC_LIST})

# 当源文件不在同一个目录时,使用set可以进行拼接
set(变量名1 ${变量名1} ${变量名2} ...)
file(GLOB SRC_1 ${PROJECT_SOURCE_DIR}/src1/*.cpp)
file(GLOB SRC_2 ${PROJECT_SOURCE_DIR}/src2/*.cpp)
# 追加(拼接)
set(SRC_1 ${SRC_1} ${SRC_2} ${TEMP})

#当源文件中有不需要的,通过list删除
file(GLOB SRC_1 ${PROJECT_SOURCE_DIR}/*.cpp)
# 移除前日志
message(STATUS "message: ${SRC_1}")
# 移除 main.cpp,注意file搜索的时候是带绝对路径的,因此删除的时候也要带上绝对路径
list(REMOVE_ITEM SRC_1 ${PROJECT_SOURCE_DIR}/main.cpp)
# 移除后日志
message(STATUS "message: ${SRC_1}")

制作动态库和静态库

有些时候我们编写的源代码并不需要将他们编译生成可执行程序,而是生成一些静态库或动态库提供给第三方使用。

# 制作静态库
add_library(库名称 STATIC 源文件1 源文件2 ...) 
# 制作动态库
add_library(库名称 SHARED 源文件1 [源文件2] ...) 
#设置生成的库的路径
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)

使用库

#静态库
# 包含静态库路径
link_directories(${PROJECT_SOURCE_DIR}/lib)
# 链接静态库
link_libraries(calc)
#动态库,动态库具有链接性 A链接了B,C,D链接了A时使用
#指定动态库位置
link_directories(${PROJECT_SOURCE_DIR}/lib)
target_link_libraries(A B C)
target_link_libraries(D A)
  • 静态库会在生成可执行程序的链接阶段被打包到可执行程序中,所以可执行程序启动,静态库就被加载到内存中了。
  • 动态库在生成可执行程序的链接阶段不会被打包到可执行程序中,当可执行程序被启动并且调用了动态库中的函数的时候,动态库才会被加载到内存

因此,在cmake中指定要链接的动态库的时候,应该将命令写到生成了可执行文件之后

常使用的宏

功能
PROJECT_SOURCE_DIR使用cmake命令后紧跟的目录,一般是工程的根目录
PROJECT_BINARY_DIR执行cmake命令的目录
CMAKE_CURRENT_SOURCE_DIR当前处理的CMakeLists.txt所在的路径
CMAKE_CURRENT_BINARY_DIRtarget 编译目录
EXECUTABLE_OUTPUT_PATH重新定义目标二进制可执行文件的存放位置
LIBRARY_OUTPUT_PATH重新定义目标链接库文件的存放位置
PROJECT_NAME返回通过PROJECT指令定义的项目名称
CMAKE_BINARY_DIR项目实际构建路径,假设在build目录进行的构建,那么得到的就是这个目录的路径

嵌套Cmake

如果项目很大,或者项目中有很多的源码目录,在通过CMake管理项目的时候如果只使用一个CMakeLists.txt,那么这个文件相对会比较复杂,有一种化繁为简的方式就是给每个源码目录都添加一个CMakeLists.txt文件(头文件目录不需要),这样每个文件都不会太复杂,而且更灵活,更容易维护。

$ tree
.
├── build
├── calc
│   ├── add.cpp
│   ├── CMakeLists.txt
│   ├── div.cpp
│   ├── mult.cpp
│   └── sub.cpp
├── CMakeLists.txt
├── include
│   ├── calc.h
│   └── sort.h
├── sort
│   ├── CMakeLists.txt
│   ├── insert.cpp
│   └── select.cpp
├── test1
│   ├── calc.cpp
│   └── CMakeLists.txt
└── test2
    ├── CMakeLists.txt
    └── sort.cpp
  • include 目录:头文件目录

  • calc 目录

    :目录中的四个源文件对应的加、减、乘、除算法

    • 对应的头文件是include中的calc.h
  • sort 目录

    :目录中的两个源文件对应的是插入排序和选择排序算法

    • 对应的头文件是include中的sort.h
  • test1 目录:测试目录,对加、减、乘、除算法进行测试

  • test2 目录:测试目录,对排序算法进行测试

嵌套Cmake的节点关系
  • 根节点CMakeLists.txt中的变量全局有效
  • 父节点CMakeLists.txt中的变量可以在子节点中使用
  • 子节点CMakeLists.txt中的变量只能在当前节点中使用
# 为cmake添加一个子节点cmake
add_subdirectory(子目录 [binary_dir] [EXCLUDE_FROM_ALL])
  • binary_dir:指定了输出文件的路径,一般不需要指定,忽略即可。
  • EXCLUDE_FROM_ALL:在子路径下的目标默认不会被包含到父路径的ALL目标里,并且也会被排除在IDE工程文件之外。用户必须显式构建在子路径下的目标。
根目录
cmake_minimum_required(VERSION 3.0)
project(test)
# 定义变量
# 静态库生成的路径
set(LIB_PATH ${CMAKE_CURRENT_SOURCE_DIR}/lib)
# 测试程序生成的路径
set(EXEC_PATH ${CMAKE_CURRENT_SOURCE_DIR}/bin)
# 头文件目录
set(HEAD_PATH ${CMAKE_CURRENT_SOURCE_DIR}/include)
# 静态库的名字
set(CALC_LIB calc)
set(SORT_LIB sort)
# 可执行程序的名字
set(APP_NAME_1 test1)
set(APP_NAME_2 test2)
# 添加子目录
add_subdirectory(calc)
add_subdirectory(sort)
add_subdirectory(test1)

calc目录

cmake_minimum_required(VERSION 3.0)
project(CALCLIB)
aux_source_directory(./ SRC)
include_directories(${HEAD_PATH})
set(LIBRARY_OUTPUT_PATH ${LIB_PATH})
add_library(${CALC_LIB} STATIC ${SRC})
  • 第3行aux_source_directory:搜索当前目录(calc目录)下的所有源文件
  • 第4行include_directories:包含头文件路径,HEAD_PATH是在根节点文件中定义的
  • 第5行set:设置库的生成的路径,LIB_PATH是在根节点文件中定义的
  • 第6行add_library:生成静态库,静态库名字CALC_LIB是在根节点文件中定义的

sort 目录

cmake_minimum_required(VERSION 3.0)
project(SORTLIB)
aux_source_directory(./ SRC)
include_directories(${HEAD_PATH})
set(LIBRARY_OUTPUT_PATH ${LIB_PATH})
add_library(${SORT_LIB} SHARED ${SRC})

test1 目录

test1 目录中的 CMakeLists.txt文件内容如下:

CMAKE
cmake_minimum_required(VERSION 3.0)
project(CALCTEST)
aux_source_directory(./ SRC)
include_directories(${HEAD_PATH})
# include_directories(${HEAD_PATH})
link_libraries(${CALC_LIB})
set(EXECUTABLE_OUTPUT_PATH ${EXEC_PATH})
add_executable(${APP_NAME_1} ${SRC})
  • 第4行include_directories:指定头文件路径,HEAD_PATH变量是在根节点文件中定义的
  • 第6行link_libraries:指定可执行程序要链接的静态库CALC_LIB变量是在根节点文件中定义的
  • 第7行set:指定可执行程序生成的路径,EXEC_PATH变量是在根节点文件中定义的
  • 第8行add_executable:生成可执行程序,APP_NAME_1变量是在根节点文件中定义的

test2 目录

test2 目录中的 CMakeLists.txt文件内容如下:

CMAKE
cmake_minimum_required(VERSION 3.0)
project(SORTTEST)
aux_source_directory(./ SRC)
include_directories(${HEAD_PATH})
set(EXECUTABLE_OUTPUT_PATH ${EXEC_PATH})
# link_directories(${LIB_PATH})
add_executable(${APP_NAME_2} ${SRC})
target_link_libraries(${APP_NAME_2} ${SORT_LIB})
  • 第四行include_directories:包含头文件路径,HEAD_PATH变量是在根节点文件中定义的
  • 第五行set:指定可执行程序生成的路径,EXEC_PATH变量是在根节点文件中定义的
  • 第六行link_directories:指定可执行程序要链接的动态库的路径,LIB_PATH变量是在根节点文件中定义的
  • 第七行add_executable:生成可执行程序,APP_NAME_2变量是在根节点文件中定义的
  • 第八行target_link_libraries:指定可执行程序要链接的动态库的名字

在生成可执行程序的时候,动态库不会被打包到可执行程序内部。当可执行程序启动之后动态库也不会被加载到内存,只有可执行程序调用了动态库中的函数的时候,动态库才会被加载到内存中,且多个进程可以共用内存中的同一个动态库,所以动态库又叫共享库。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值