CMake 实战练习

news/2024/12/23 8:01:11/

本文将演示如何使用 CMake 管理一个中等复杂度的项目,从创建项目到编译和运行的整个过程,涵盖了从基本配置到高级特性的实际应用。

实战内容如下:

  1. 创建 CMakeLists.txt 文件:定义项目、库、可执行文件和测试。
  2. 编写源代码和测试:编写代码和测试文件。
  3. 创建构建目录:保持源代码目录整洁。
  4. 配置项目:生成构建系统文件。
  5. 编译项目:生成目标文件。
  6. 运行可执行文件:执行程序。
  7. 运行测试:验证功能正确性。
  8. 使用自定义命令和目标:执行额外操作。
  9. 跨平台和交叉编译:支持不同平台和架构。

构建一个简单的 C++ 项目

假设我们有一个项目,包含一个主程序和一个库,库中有两个不同的功能模块。

项目结构如下:

MyProject/
├── CMakeLists.txt
├── src/
│   ├── main.cpp
│   ├── lib/
│   │   ├── module1.cpp
│   │   ├── module2.cpp
│   ├── include/
│       └── mylib.h
└── tests/├── test_main.cpp└── CMakeLists.txt

1、创建 CMakeLists.txt 文件

1.1 根目录 CMakeLists.txt 文件

在 MyProject 根目录下创建一个 CMakeLists.txt 文件:

实例

cmake_minimum_required(VERSION 3.10)   # 指定最低 CMake 版本
project(MyProject VERSION 1.0)          # 定义项目名称和版本

# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# 包含头文件路径
include_directories(${PROJECT_SOURCE_DIR}/src/include)

# 添加子目录
add_subdirectory(src)
add_subdirectory(tests)

1.2 src 目录 CMakeLists.txt 文件

在 src 目录下创建一个 CMakeLists.txt 文件:

实例

# 创建库目标
add_library(MyLib STATIC
    lib/module1.cpp
    lib/module2.cpp
)

# 指定库的头文件
target_include_directories(MyLib PUBLIC ${CMAKE_SOURCE_DIR}/src/include)

# 创建可执行文件目标
add_executable(MyExecutable main.cpp)

# 链接库到可执行文件
target_link_libraries(MyExecutable PRIVATE MyLib)

1.3 tests 目录 CMakeLists.txt 文件

在 tests 目录下创建一个 CMakeLists.txt 文件:

实例

# 查找 GTest 包
find_package(GTest REQUIRED)
include_directories(${GTEST_INCLUDE_DIRS})

# 创建测试目标
add_executable(TestMyLib test_main.cpp)

# 链接库和 GTest 到测试目标
target_link_libraries(TestMyLib PRIVATE MyLib ${GTEST_LIBRARIES})


2、编写源代码和测试

以下是各个文件的代码:

2.1 src/main.cpp 文件代码

实例

#include <iostream>
#include "mylib.h"

int main() {
    std::cout << "Hello, CMake!" << std::endl;
    return 0;
}

2.2 src/lib/module1.cpp 文件代码

实例

#include "mylib.h"

// Implementation of module1

2.3 src/lib/module2.cpp 文件代码

实例

#include "mylib.h"

// Implementation of module2

2.4 src/include/mylib.h 文件代码

实例

#ifndef MYLIB_H
#define MYLIB_H

// Declarations of module functions

#endif // MYLIB_H

2.5 tests/test_main.cpp 文件代码

实例

#include <gtest/gtest.h>

// Test cases for MyLib
TEST(MyLibTest, BasicTest) {
    EXPECT_EQ(1, 1);
}


3、创建构建目录

在项目根目录下创建一个构建目录:

mkdir build
cd build

4、配置项目

在构建目录中运行 CMake 以配置项目:

cmake ..

5、编译项目

使用生成的构建系统文件进行编译,假设生成了 Makefile:

make

6、运行可执行文件

编译完成后,可以运行生成的可执行文件:

./MyExecutable

7、运行测试

使用生成的测试目标进行测试:

./TestMyLib

8、使用自定义命令和目标

8.1 自定义命令

在 src/CMakeLists.txt 文件中添加自定义命令:

add_custom_command(TARGET MyExecutablePOST_BUILDCOMMAND ${CMAKE_COMMAND} -E echo "Build complete!"
)

8.2 自定义目标

在 src/CMakeLists.txt 文件中添加自定义目标:

add_custom_target(runCOMMAND ${CMAKE_BINARY_DIR}/MyExecutableDEPENDS MyExecutable
)

运行自定义目标:

make run

9、跨平台和交叉编译

9.1 指定平台

如果需要指定平台进行构建,可以在运行 CMake 时指定平台:

cmake -DCMAKE_SYSTEM_NAME=Linux ..

9.2 使用工具链文件

创建一个工具链文件 toolchain.cmake:

set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)

使用工具链文件进行构建:

cmake -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake ..

http://www.ppmy.cn/news/1557413.html

相关文章

【LeetCode: 876. 链表的中间结点 + 链表】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

3D开发工具HOOPS助力造船业加速设计与数字化转型

随着造船业对设计、高效精准建模和快速原型开发的需求不断增加&#xff0c;先进的3D技术逐渐成为推动行业创新的核心工具。Tech Soft 3D的HOOPS SDK作为行业领先的开发平台&#xff0c;已被NAPA、Herbert-ABS和三菱造船有限公司等全球造船业领导者所采用&#xff0c;帮助企业加…

华水967数据结构2012真题---选择题部分

二 、 单项选择题 1. 线性表的顺序存储结构是一种【】的存储结构。 A. 散列存取 B. 索 引 存 取 C. 随机存取 D. 顺序存取 答案&#xff1a;C 解析&#xff1a; A. 散列存取&#xff1a;顺序存储结构并不依赖于散列函数来确定元素的存储位置&#xff0c;因此A选项不正确。 B.…

tryhackme-Pre Security-HTTP in Detail(HTTP的详细内容)

任务一&#xff1a;What is HTTP(S)?&#xff08;什么是http&#xff08;s&#xff09;&#xff09; 1.What is HTTP? (HyperText Transfer Protocol)&#xff08;什么是 HTTP&#xff1f;&#xff08;超文本传输协议&#xff09;&#xff09; http是你查看网站的时候遵循的…

《计算机组成及汇编语言原理》阅读笔记:p28-p47

《计算机组成及汇编语言原理》学习第 3 天&#xff0c;p28-p47 总结&#xff0c;总计 20 页。 一、技术总结 1.Virtual Machine 2.stack 3.The fetch-execute Cycle 在控制单元(Control Unit, CU)里面有一个指令寄存器(Instruction Register, IR)和一个程序计数器(Program…

nano编辑器的使用

nano 是一个非常简单易用的命令行文本编辑器&#xff0c;它常用于在 Linux 或类 Unix 系统中快速编辑文件&#xff0c;特别适用于需要修改配置文件或快速编辑文本的场景。以下是一些常见的 nano 使用技巧和基本操作。 1. 打开文件 要使用 nano 编辑文件&#xff0c;打开终端并…

在 .NET 5.0 运行 .NET 8.0 教程:使用 ASP.NET Core 创建 Web API

前言 因为我本机安装的是vs2019&#xff0c;所以我在使用vs创建项目的时候&#xff0c;只能选择.NET 5.0&#xff0c;而无法选择.NET 8.0 在网上有看到说用vs2019使用.net 8.0 &#xff0c;但是感觉不可靠&#xff0c;要用还是安装vs2022吧。 我因为不想要安装vs2022。 但是微…

docker打包镜像并迁移:如何从A服务器打包docker镜像到B服务器上容器中运行

1.在A服务器上&#xff0c;查看docker镜像 docker images会显示当前的服务器上已有的镜像 2.在A服务器上&#xff0c;将所需要的镜像打包 docker save -o shuai_docker.tar xxx(镜像名):vxx(镜像版本)会出现&#xff1a;xxxxx:Loading layer [>] xxkB/xxkB字样 3.将shua…