前言
在 ros 中经常使用cmake文件进行编译,其中进行了可执行文件添加和相关库的添加但是没有深入了解cmake的具体操作所以今天进行学习。
cmake 操作内容如下
创建 CMakeLists.txt 文件:定义项目、库、可执行文件和测试。
编写源代码和测试:编写代码和测试文件。
创建构建目录:保持源代码目录整洁。
配置项目:生成构建系统文件。
编译项目:生成目标文件。
运行可执行文件:执行程序。
运行测试:验证功能正确性。
使用自定义命令和目标:执行额外操作。
跨平台和交叉编译:支持不同平台和架构。
构建一个简单的 C++ 项目
假设我们有一个项目,包含一个主程序和一个库,库中有两个不同的功能模块。
项目结构如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
MyProject/
├── CMakeLists.txt
├── src/
│ ├── main.cpp
│ ├── lib/
│ │ ├── module1.cpp
│ │ ├── module2.cpp
│ ├── include/
│ └── mylib.h
└── tests/
├── test_main.cpp
└── CMakeLists.txt
创建 CMakeLists.txt 文件
根目录 CMakeLists.txt 文件
在 MyProject 根目录下创建一个 CMakeLists.txt 文件:
1 |
|
src 目录 CMakeLists.txt 文件
在 src 目录下创建一个 CMakeLists.txt 文件:
1 |
|
tests 目录 CMakeLists.txt 文件
在 tests 目录下创建一个 CMakeLists.txt 文件:
1 |
|
编写源代码和测试
以下是各个文件的代码:
src/main.cpp 文件代码
1 |
|
src/lib/module1.cpp 文件代码
1 |
|
src/lib/module2.cpp 文件代码
1 |
|
src/include/mylib.h 文件代码
1 |
|
tests/test_main.cpp 文件代码
1 |
|
创建构建目录
在项目根目录下创建一个构建目录:
1 | mkdir build |
配置项目
在构建目录中运行 CMake 以配置项目:
1 | cmake .. |
编译项目
1 | make |
运行可执行文件
编译完成后,可以运行生成的可执行文件:
1 | ./MyExecutable |
运行测试
使用生成的测试目标进行测试:
1 | ./TestMyLib |
使用自定义命令和目标
自定义命令
在 src/CMakeLists.txt 文件中添加自定义命令:
1 |
|
自定义目标
在 src/CMakeLists.txt 文件中添加自定义目标:
1 |
|
运行自定义目标:
1 | make run |
跨平台和交叉编译
指定平台
如果需要指定平台进行构建,可以在运行 CMake 时指定平台:
1 | cmake -DCMAKE_SYSTEM_NAME=Linux .. |
使用工具链文件
创建一个工具链文件 toolchain.cmake:
1 | set(CMAKE_SYSTEM_NAME Linux) |
使用工具链文件进行构建:
1 | cmake -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake .. |
实践操作
完全按照教程中的配置进行cmake编译完全没有办法生成makefile从而无法make
从简单的开始实践:
单个文件使用外部库的情况
1 | cmake_minimum_required (VERSION 3.10) |
多个文件包含personal.h,personal.cpp,main.cpp
src/ # 源代码目录
├── CMakeLists.txt # src目录的CMake配置文件
├── include/ # 头文件目录
│ └── personal.h # 自定义头文件
├── personal.cpp # 自定义源文件
└── main.cpp # 主程序文件1
2
3
4
5
6
7cmake_minimum_required (VERSION 2.8)
project (personaldata)
include_directories(${PROJECT_SOURCE_DIR}/include)
add_executable(personaldata main.cpp personal.cpp)
关于诺干源文件一起编译
如果同一目录下有无穷多源文件,那么一个一个添加就很慢了。此时可以使用cmake中的函数存储这些源文件,aux_source_directory(dir var) 他的作用是把dir目录中的所有源文件都储存在var变量中,然后需要用到源文件的地方用 变量var来取代此时 CMakeLists.txt 可以这样优化。
1 | cmake_minimum_required (VERSION 2.8) |
但是不推荐这样使用因为:
不包含头文件:
只收集源文件(.cpp/.c),不包含头文件(.h)
头文件需要单独使用
include_directories()处理
不递归子目录
只扫描指定目录本身,不会进入子目录
如果需要子目录文件,需在每个子目录使用此命令或使用
add_subdirectory()
1 | set(SRC_FILES |
1 | cmake_minimum_required (VERSION 2.8) |