CMake
一、CMake概述#
CMake是一个跨平台的项目构建工具。编写完CMakeLists.txt(注意文件名称是固定的,区分大小写)后,执行cmake命令,生成Makefile文件和其他中间过程文件。当然你也可以手动去编写Makefile文件,但是编写的工具量比较大,而且依赖关系也比较多,比较容易出错。
从项目源码到可执行文件的流程图:
项目的一般目录结构:
单独新建一个空目录 build
用来保存cmake命令后的中间文件,不会把原来的目录结构搞混乱,而且看起来更整洁。
二、CMakeLists.txt#
- CMakeLists.txt语法
一些内置预定义变量以及含义:
预定义变量 | 含义 |
---|---|
PROJECT_SOURCE_DIR | 工程的根目录 |
PROJECT_NAME | 返回通过project命令定义的项目名 |
PROJECT_BINARY_DIR | 运行cmake命令的目录,通常是在项目下创建build目录,并执行命令 |
CMAKE_CURRENT_SOURCE_DIR | 当前处理CMakeLists.txt所在目录 |
CMAKE_CURRENT_BINARY_DIR | target编译目录(即目标文件输出目录) |
CMAKE_CURRENT_LIST_DIR | CMakeLists.txt的目录 |
CMAKE_CURRENT_LIST_LINE | 当前所在行(即该变量执行时的所在行) |
通过一个具体的例子,验证表格中的内置变量是否正确:
分析上述结果,变量 EXECUTABLE_OUTPUT_PATH
和 LIBRARY_OUTPUT_PATH
为空,内置无效。
- CMakeLists.txt模板:
# 指定cmake版本
cmake_minimun_required(VERSION x.x)
# 指定项目名称
project(项目名称xxxx)
# 添加预处理定义,该功能已被其他命令替换(可选)
add_definitions(编译选项)
# 为源文件的添加编译选项(可选)
add_compile_options(选项1 选项2 选项...)
# 指定头文件目录,若存在多个用空格隔开
include_directories(目录1 目录2 目录...)
# 搜索指定目录下所有源文件,可以将所有源文件赋值给一个变量
# 如果不想在add_executable内一个一个写源文件的话,aux_source_directory就很有用
aux_source_directory(目录 变量)
# 设置变量,变量名一般全大写
set(变量 文件名or路径or其他)
# 指定源文件生成库文件(默认生成静态库)。可将static替换为shared,则生成动态库
add_library(库文件名 static 源文件1 源文件2 源文件...)
# 指定库文件目录
link_directories(目录)
# 指定的源文件来生成目标可执行文件
add_executable(目标可执行文件名 源文件)
# 设置链接库,即为目标可执行文件添加需要的库文件
target_link_libraries(目标可执行文件名 库文件名1 库文件名2 库文件名...)
# 输出测试,打印测试字符串,一般用于console log(可选)
message(字符串1 字符串2或变量 字符串...)
# 指定安装目录,一般需要先指定按照目标前缀,例如:/usr,执行make install后,可执行文件安装到:/usr/bin目录下(在X86主机测试)。如果没有指定前缀
# 默认会被安装到 /usr/local/bin 目录下(在树莓派4B测试)
set(CMAKE_INSTALL_PREFIX /usr)
install(TARGETS ${PROJECT_NAME} DESTINATION bin)
# 查找目标依赖包
find_package()
2024-06-20(补充)
find_package() 查找目标包
(CMakeLists.txt部分内容)
find_package(PkgConfig REQUIRED)
pkg_check_modules (DBUS REQUIRED IMPORTED_TARGET dbus-1)
pkg_check_modules (GLIB REQUIRED IMPORTED_TARGET glib-2.0)
pkg_check_modules (GIO REQUIRED IMPORTED_TARGET gio-2.0)
MESSAGE(STATUS "DBUS dirs:" ${DBUS_INCLUDE_DIRS})
MESSAGE(STATUS "DBUS lib:" ${DBUS_LIBRARIES})
MESSAGE(STATUS "glib-2.0 dirs:" ${GLIB_INCLUDE_DIRS})
MESSAGE(STATUS "glib-2.0 lib:" ${GLIB_LIBRARIES})
MESSAGE(STATUS "gio-2.0 dirs:" ${GIO_INCLUDE_DIRS})
MESSAGE(STATUS "gio-2.0 lib:" ${GIO_LIBRARIES})
message("PROJECT_SOURCE_DIR:" ${PROJECT_SOURCE_DIR})
cmake命令后的截图:
二、模块化#
项目下有多个模块:
pi@c8d2b2520c00:/workspace/distro$ tree buildroot-external/app/supervisor/
buildroot-external/app/supervisor/
├── CMakeLists.txt
├── README.md
└── src
├── bluetooth
│ ├── CMakeLists.txt
│ ├── bluetooth.cpp
│ └── bluetooth.hpp
├── dbus
│ ├── CMakeLists.txt
│ ├── dbus.cpp
│ └── dbus.hpp
├── hardware
│ ├── CMakeLists.txt
│ ├── hardware.cpp
│ └── hardware.hpp
├── log
│ ├── CMakeLists.txt
│ ├── log.cpp
│ └── log.hpp
├── main.cpp
├── mqtt
│ ├── CMakeLists.txt
│ ├── mqtt.cpp
│ └── mqtt.hpp
├── network
│ ├── CMakeLists.txt
│ ├── network.cpp
│ └── network.hpp
└── os
├── CMakeLists.txt
├── os.cpp
└── os.hpp
8 directories, 24 files
每一个模块下都有一个 CMakeLists.txt,在项目的顶层目录下也有一个 CMakeLists.txt。
这里看一下 bluetooth 模块的 CMakeLists.txt
add_library(bluetooth STATIC bluetooth.cpp)
target_link_libraries(bluetooth)
target_include_directories(bluetooth PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
再看一下,项目顶层目录下的 CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(supervisor)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
find_package(PkgConfig REQUIRED)
pkg_check_modules(DBusCxx REQUIRED dbus-cxx-2.0)
pkg_check_modules(jsoncpp REQUIRED jsoncpp)
pkg_check_modules(spdlog REQUIRED spdlog)
# 设置源文件目录
set(SOURCES src/main.cpp)
# 添加子目录
add_subdirectory(src/hardware)
add_subdirectory(src/mqtt)
add_subdirectory(src/os)
add_subdirectory(src/network)
add_subdirectory(src/bluetooth)
add_subdirectory(src/dbus)
add_subdirectory(src/log)
# 创建可执行文件
add_executable(${PROJECT_NAME} ${SOURCES})
target_include_directories(${PROJECT_NAME} PRIVATE ${jsoncpp_INCLUDE_DIRS} ${DBusCxx_INCLUDE_DIRS} ${spdlog_INCLUDE_DIRS})
# 链接 Paho MQTT 和 nlohmann JSON 库
target_link_libraries(${PROJECT_NAME}
${jsoncpp_LIBRARIES}
hardware
mqtt # 链接 mqtt 库
os # 链接 os 库
network # 链接 network 库
bluetooth # 链接 bluetooth 库
dbus # 链接 dbus 库
log # 链接 log 库
)
# 安装
install(TARGETS ${PROJECT_NAME} DESTINATION bin)
疑点#
为什么直接链接下面的库就可以,而不需要指定库目录?
target_link_libraries(${PROJECT_NAME}
pthread
zlog
mqtt
cjson
)
原因在于这几个动态库都在默认系统动态链接库配置文件记录的位置。系统动态链接库配置文件是:/etc/ld.so.conf
,文件内容如下
pi@pi-NMH-WCX9:~/workspace/connectedhomeip$ cat /etc/ld.so.conf
include /etc/ld.so.conf.d/*.conf
pi@pi-NMH-WCX9:~/workspace/connectedhomeip$ ls /etc/ld.so.conf.d/
fakeroot-x86_64-linux-gnu.conf libc.conf x86_64-linux-gnu.conf
pi@pi-NMH-WCX9:~/workspace/connectedhomeip$ cat /etc/ld.so.conf.d/libc.conf
# libc default configuration
/usr/local/lib
pi@pi-NMH-WCX9:~/workspace/connectedhomeip$ cat /etc/ld.so.conf.d/fakeroot-x86_64-linux-gnu.conf
/usr/lib/x86_64-linux-gnu/libfakeroot
pi@pi-NMH-WCX9:~/workspace/connectedhomeip$ cat /etc/ld.so.conf.d/x86_64-linux-gnu.conf
# Multiarch support
/usr/local/lib/x86_64-linux-gnu
/lib/x86_64-linux-gnu
/usr/lib/x86_64-linux-gnu
查看动态链接库登记的目录下有哪些库:
# /usr/local/lib/ 目录下可以看到有 zlog库文件
pi@pi-NMH-WCX9:~/workspace/connectedhomeip$ ll /usr/local/lib | grep zlog
-rw-rw-r-- 1 caojun caojun 746678 9月 18 15:04 libzlog.a
lrwxrwxrwx 1 root root 12 9月 18 15:05 libzlog.so -> libzlog.so.1*
lrwxrwxrwx 1 root root 14 9月 18 15:05 libzlog.so.1 -> libzlog.so.1.2*
-rwxrwxr-x 1 caojun caojun 375048 9月 18 15:04 libzlog.so.1.2*
# /usr/lib/x86_64-linux-gnu/ 目录下有 pthread 库文件
pi@pi-NMH-WCX9:~/workspace/connectedhomeip$ ll /usr/lib/x86_64-linux-gnu/ | grep pthread
lrwxrwxrwx 1 root root 14 9月 28 2023 libgpgme-pthread.so.11 -> libgpgme.so.11
-rw-r--r-- 1 root root 8 5月 7 2024 libpthread.a
-rw-r--r-- 1 root root 21448 5月 7 2024 libpthread.so.0
三、参考地址#
Cmake知识----编写CMakeLists.txt文件编译C/C++程序
作者:caojun97
出处:https://www.cnblogs.com/caojun97/p/18122460
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 推荐几款开源且免费的 .NET MAUI 组件库
· 实操Deepseek接入个人知识库
· 易语言 —— 开山篇
· Trae初体验
2023-05-25 SQL Server:分页查询