Cmake 语法与实战入门
语法
1指定cmake最小版本
1 | cmake_minimum_required(VERSION 3.4.1) |
2设置项目名称
1 | project(demo) |
它会引入两个变量 demo_BINARY_DIR 和 demo_SOURCE_DIR,
同时,cmake 自动定义了两个等价的变量 PROJECT_BINARY_DIR 和 PROJECT_SOURCE_DIR。
3设置编译类型
1 2 3 | add_executable(demo demo.cpp) # 生成可执行文件 add_library(common STATIC util.cpp) # 生成静态库 add_library(common SHARED util.cpp) # 生成动态库或共享库 |
add_library 默认生成是静态库,通过以上命令生成文件名字,
在 Linux 下是:demo libcommon.a libcommon.so
在 Windows 下是:demo.exe common.lib common.dll
4指定编译包含的源文件
4- 1明确指出包含哪些源文件
1 | add_library(demo demo.cpp test.cpp util.cpp) |
4-2搜索所有的cpp文件
aux_source_directory(dir VAR) 发现一个目录(dir)下所有的源代码文件并将列表存储在一个变量(VAR)中。
1 2 | aux_source_directory(. SRC_LIST) # 搜索当前目录下的所有.cpp文件 add_library(demo ${SRC_LIST}) |
4-3自定义搜索规则
1 2 3 4 5 6 7 8 9 10 11 12 13 | #1file模式 搜索同目录+protocol目录所有的cpp文件 file(GLOB SRC_LIST "*.cpp" "protocol/*.cpp" ) add_library(demo ${SRC_LIST}) # 2file模式 分开目录搜索添加 file(GLOB SRC_LIST "*.cpp" )#单独搜索本目录所有cpp 存放变量SRC_LIST file(GLOB SRC_PROTOCOL_LIST "protocol/*.cpp" )#单独搜索protocol目录所有cpp 存放变量SRC_PROTOCOL_LIST add_library(demo ${SRC_LIST} ${SRC_PROTOCOL_LIST}) # 3 aux模式 aux_source_directory(. SRC_LIST)##单独搜索本目录所有cpp 存放变量SRC_LIST aux_source_directory(protocol SRC_PROTOCOL_LIST)#单独搜索protocol目录所有cpp 存放变量SRC_PROTOCOL_LIST add_library(demo ${SRC_LIST} ${SRC_PROTOCOL_LIST}) |
5-1设置包含的目录
如果src/math.cpp和include/math.h不在同一个文件夹,math.cpp中引用math.h头文件
模式1 使用相对路径 include/math.h
模式2 使用直接路径math.h 但是camke要指定包含include文件夹
1 2 3 4 5 | include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/include ) |
5-2添加一个子目录并构建该子目录
1 | add_subdirectory (source_dir [binary_dir] [EXCLUDE_FROM_ALL]) |
source_dir
必选参数。该参数指定一个子目录,子目录下应该包含CMakeLists.txt
文件和代码文件。子目录可以是相对路径也可以是绝对路径,如果是相对路径,则是相对当前目录的一个相对路径。-
binary_dir
可选参数。该参数指定一个目录,用于存放输出文件。可以是相对路径也可以是绝对路径,如果是相对路径,则是相对当前输出目录的一个相对路径。如果该参数没有指定,则默认的输出目录使用source_dir
。 -
EXCLUDE_FROM_ALL
可选参数。当指定了该参数,则子目录下的目标不会被父目录下的目标文件包含进去,父目录的CMakeLists.txt
不会构建子目录的目标文件,必须在子目录下显式去构建。例外情况:当父目录的目标依赖于子目录的目标,则子目录的目标仍然会被构建出来以满足依赖关系(例如使用了target_link_libraries)
。 - 例子

6-1查找指定的库文件
find_library(VAR name path)查找到指定的预编译库,并将它的路径存储在变量中。
默认的搜索路径为 cmake 包含的系统库,因此如果是 NDK 的公共库只需要指定库的name 即可(不需path)。
1 | find_library(log-lib,log) |
类似的命令还有 find_file()、find_path()、find_program()、find_package()。
6-2设置target需要链接的库
1 | target_link_libraries( # 目标库 demo # 目标库需要链接的库 ${log-lib} ) |
在 Windows 下,系统会根据链接库目录,搜索xxx.lib 文件,Linux 下会搜索 xxx.so 或者 xxx.a 文件,如果都存在会优先链接动态库(so 后缀)。
6-2-1指定链接动态库或静态库
1 2 | target_link_libraries(demo libface.a) # 链接libface.a target_link_libraries(demo libface.so) # 链接libface.so |
2. 指定全路径
1 2 | target_link_libraries(demo ${CMAKE_CURRENT_SOURCE_DIR}/libs/libface.a) target_link_libraries(demo ${CMAKE_CURRENT_SOURCE_DIR}/libs/libface.so) |
3. 指定链接多个库
1 2 3 4 5 | target_link_libraries(demo ${CMAKE_CURRENT_SOURCE_DIR}/libs/libface.a boost_system.a boost_thread pthread) |
7设置变量
set 直接设置变量的值
1 2 | set (SRC_LIST main.cpp test.cpp) add_executable(demo ${SRC_LIST}) |
set 追加设置变量的值
1 2 3 | set (SRC_LIST main.cpp) set (SRC_LIST ${SRC_LIST} test.cpp) add_executable(demo ${SRC_LIST}) |
常用变量
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:重新定义目标链接库文件的存放位置
测试例程
例子1 文件包含模式-非库引用
CMakeLists.txt
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 父目录下的CMakeLists.txt cmake_minimum_required(VERSION 3.10.2) project(test) #1手动设置指定文件 set (Current_LIST main.cpp ) set (SRC_LIST src/API_Cout.cpp) #不需要指定头文件 #2自动搜所文件目录 #aux_source_directory(. Current_LIST) # 搜索当前.目录下的所有.cpp文件 #aux_source_directory(./src SRC_LIST) # 搜索src目录下的所有.cpp文件 add_executable(demo ${Current_LIST} ${SRC_LIST}) |
main.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #ifndef MAIN_CPP #define MAIN_CPP #include "src/API_Cout.h" #include <iostream> int main( int argc, char ** argv) { std::cout << "In main..." << std::endl; test( "hello, world!" ); return 0; } #endif MAIN_CPP |
API_Cout.h
1 2 3 4 5 6 7 8 9 | #ifndef COUT_H #define COUT_H #include <string> void test(std:: string str); #endif |
API_Cout.cpp
1 2 3 4 5 6 7 8 9 10 11 12 | #ifndef COUT_CPP #define COUT_CPP #include "API_Cout.h" #include <iostream> void test(std:: string str) { std::cout << str << std::endl; } #endif |
编译运行结果
直接命令行
1 2 3 | cd build camke .. make |
vscode-View-terminal
例子2 文件包含模式-打包库引用
同例子1样的代码
打包成库参与引用
src多了一个cmakelist.txt
注意事项
1所有的cmaklist中涉及到的变量不能同名
2 代码用的是相对路径引用
1 | #include "src/API_Cout.h" |
例子3 文件包含模式-打包库引用
正常模式1 使用了相对路径引用,不需要include_directories包含引用文件路径
正常模式2 不使用了相对路径引用,需要include_directories包含引用文件路径
主函数采用非相对引用
1 | #include "API_Cout.h" //关键地方 不是相对引用 src/API_Cout.h |
cmake需要包含文件路劲
1 | include_directories(src)#关键 不是相对引用 需要单独制定包含 |
include_directories命令使得不使用相对路径也可以包含引用文件。
缺点,但是不建议这么干,代码逻辑混乱
优点,可能一些复杂的工程借助于此,编辑样例的时候省去了一堆相对路径查找和包含。
例子4 -1多项目,各自工程独立文件夹编译
CMakeLists.txt
1 2 3 4 5 6 7 | # 父目录下的CMakeLists.txt cmake_minimum_required(VERSION 3.10.2) project(test) add_subdirectory( "v1_Test" ) add_subdirectory( "v2_Test" ) add_subdirectory( "v3_Test" ) |
CMakeLists.txt
1 2 3 4 5 6 7 8 9 | #1手动设置指定文件 set (Current_LIST main.cpp ) set (SRC_LIST src/API_Cout.cpp) #不需要指定头文件 #2自动搜所文件目录 #aux_source_directory(. Current_LIST) # 搜索当前.目录下的所有.cpp文件 #aux_source_directory(./src SRC_LIST) # 搜索src目录下的所有.cpp文件 add_executable(demo1 ${Current_LIST} ${SRC_LIST}) |
1 2 3 4 5 6 7 8 9 | #1手动设置指定文件 set (Current_LIST main.cpp ) set (SRC_LIST src/API_Cout.cpp) #不需要指定头文件 #2自动搜所文件目录 #aux_source_directory(. Current_LIST) # 搜索当前.目录下的所有.cpp文件 #aux_source_directory(./src SRC_LIST) # 搜索src目录下的所有.cpp文件 add_executable(demo2 ${Current_LIST} ${SRC_LIST}) |
1 2 3 4 5 6 7 8 9 | #1手动设置指定文件 set (Current_LIST main.cpp ) set (SRC_LIST src/API_Cout.cpp) #不需要指定头文件 #2自动搜所文件目录 #aux_source_directory(. Current_LIST) # 搜索当前.目录下的所有.cpp文件 #aux_source_directory(./src SRC_LIST) # 搜索src目录下的所有.cpp文件 add_executable(demo3 ${Current_LIST} ${SRC_LIST}) |
编译
1 2 3 | cd build camke .. make |
例子4 -2多项目,各自工程使用共同文件夹编译
CMakeLists.txt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | cmake_minimum_required(VERSION 2.6) project(tcp) #自动连接模式 #1将文件夹下全部文件链接到 src #aux_source_directory(. src) #将src里面的所有文件链接用于生成可执行文件 #add_executable(project1 ${src}) #手动添加模式 #1测试-生成可执行文件main add_executable(main src/main.cpp) add_executable(client src/client.cpp) add_executable(Server src/Server.cpp) add_executable(http_client src/http_client.cpp) #设置可执行文件的输出目录 SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) |
src源码地址
可执行文件夹
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
2020-01-06 py
2018-01-06 Arduino 433 + 串口
2018-01-06 433 模块 ARDUINO测试