当前位置: 首页 > news >正文

一文学会CMakeLists.txt: CMake现代C++跨平台工程化实战

你能学到什么?

朋友们好久不见,我是alibli,好久没有更新博客了。今天本人将通过构造一个实际的虚拟小项目,来让你彻底掌握CMake跨平台工程构建,学会CMakeLists.txt语法。该项目实现了一个简单的平方、立方的计算程序,只为演示工程构建方法。

每一行代码都会有非常非常详细的解释!

你将掌握如下内容:

  1. 构建静态库
  2. 构建动态库
  3. 构建可执行程序
  4. 动态库如何调用静态库
  5. 可执行程序如何调用动态库

项目整体构建

项目目录:

calculator_project/
├── CMakeLists.txt                 # 外层主 CMake 文件
├── math_utils/                    # 静态库源码
│   ├── CMakeLists.txt
│   ├── MathUtils.h
│   └── MathUtils.cpp
├── calculator/                    # 动态库(依赖静态库)
│   ├── CMakeLists.txt
│   ├── Calculator.h
│   └── Calculator.cpp
└── app/                           # 主程序├── CMakeLists.txt└── main.cpp

外层CMakeLists.txt

# calculator_project/CMakeLists.txt# 1. 指定项目所需的最低 CMake 版本
#    如果用户系统中的 CMake 版本低于 3.10,会报错
cmake_minimum_required(VERSION 3.10)# 2. 定义项目名称为 "CalculatorProject"
#    LANGUAGES CXX 表示这是一个 C++ 项目
#    CMake 会自动查找 C++ 编译器(如 g++)
project(CalculatorProject LANGUAGES CXX)# 3. 设置 C++ 标准为 C++17
#    要求编译器必须支持 C++17
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)# 4. 禁用编译器特定的扩展(如 GNU 扩展)
#    强制使用标准 C++,提高可移植性
set(CMAKE_CXX_EXTENSIONS OFF)# 5. 启用测试支持(即使现在不用,也先打开)
#    后续可以用 ctest 命令运行测试
enable_testing()# 6. 添加子目录 math_utils
#    CMake 会进入 math_utils/ 目录并读取其 CMakeLists.txt
#    该目录将构建一个静态库
add_subdirectory(math_utils)# 7. 添加子目录 calculator
#    该目录将构建一个动态库,依赖上面的静态库
add_subdirectory(calculator)# 8. 添加子目录 app
#    构建主程序,链接动态库
add_subdirectory(app)

静态库构建

进入math_utils目录

CMakeLists.txt

# calculator_project/math_utils/CMakeLists.txt# 1. 定义一个静态库目标,名为 "math_utils"
#    STATIC 表示生成静态库(.a 文件)
#    源文件列表:MathUtils.cpp
add_library(math_utils STATICMathUtils.cpp
)# 2. 设置目标 math_utils 的头文件搜索路径
#    PUBLIC 表示:
#      - math_utils 自己需要这些头文件(PRIVATE 部分)
#      - 链接 math_utils 的目标也能看到这些头文件(INTERFACE 部分)
#    ${CMAKE_CURRENT_SOURCE_DIR} 是当前目录(即 math_utils/)
#    所以其他代码可以 #include "MathUtils.h"
target_include_directories(math_utilsPUBLIC ${CMAKE_CURRENT_SOURCE_DIR}
)# 3. 关键:启用 PIC,以便被动态库链接
set_target_properties(math_utils PROPERTIESPOSITION_INDEPENDENT_CODE ON
)# 4. 为 math_utils 添加编译定义(可选)
#    这里定义一个宏 MATH_UTILS_VERSION="1.0"
#    在 MathUtils.cpp 中可以用 #ifdef MATH_UTILS_VERSION 条件编译
target_compile_definitions(math_utilsPRIVATE MATH_UTILS_VERSION=\"1.0\"
)# 5. 输出一条状态信息,帮助调试
#    构建时会显示:-- Building static library: math_utils
message(STATUS "Building static library: math_utils")

MathUtils.h

// calculator_project/math_utils/MathUtils.h23 #ifndef MATH_UTILS_H4 #define MATH_UTILS_H56 // 简单的数学工具类(静态库提供)7 class MathUtils {8 public:9     // 计算平方10     static double square(double x);1112     // 计算立方13     static double cube(double x);14 };1516 #endif // MATH_UTILS_H

MathUtils.cpp

// calculator_project/math_utils/MathUtils.cpp#include "MathUtils.h"
#include <iostream>// 实现平方函数
double MathUtils::square(double x) {return x * x;
}// 实现立方函数
double MathUtils::cube(double x) {return x * x * x;
}// 如果定义了版本宏,打印版本(用于验证独立编译)
#ifdef MATH_UTILS_VERSION
#include <iostream>
void print_version() {std::cout << "MathUtils Version: " << MATH_UTILS_VERSION << std::endl;
}
#endif

动态库构建

进入calculator目录

CMakeLists.txt

# calculator_project/calculator/CMakeLists.txt# 1. 定义一个共享库(动态库),名为 "calculator"
#    SHARED 表示生成 .so 文件(Linux)或 .dll(Windows)
#    源文件:Calculator.cpp
add_library(calculator SHAREDCalculator.cpp
)# 2. 设置 calculator 的头文件路径
#    PUBLIC:自己用 + 暴露给使用者
target_include_directories(calculatorPUBLIC ${CMAKE_CURRENT_SOURCE_DIR}
)# 3. 链接依赖:calculator 依赖 math_utils 静态库
#    PRIVATE 表示 math_utils 仅 calculator 内部使用,不暴露给主程序
#    但主程序仍能通过 calculator 调用 MathUtils 的功能
target_link_libraries(calculatorPRIVATE math_utils
)# 4. 为动态库添加版本号
#    这会影响生成的文件名,如 libcalculator.so.1.0
set_target_properties(calculator PROPERTIESVERSION 1.0SOVERSION 1
)# 5. 输出状态信息
message(STATUS "Building shared library: calculator (depends on math_utils)")

Caculator.h

// calculator_project/calculator/Calculator.h#ifndef CALCULATOR_H
#define CALCULATOR_H// 计算器类,使用 MathUtils 提供的功能
class Calculator {
public:// 计算一个数的平方(调用静态库)double square(double x);// 计算一个数的立方(调用静态库)double cube(double x);
};#endif // CALCULATOR_H

Caculator.cpp

// calculator_project/calculator/Calculator.cpp#include "Calculator.h"
#include "MathUtils.h"  // 包含静态库头文件// 使用 MathUtils::square
double Calculator::square(double x) {return MathUtils::square(x);
}// 使用 MathUtils::cube
double Calculator::cube(double x) {return MathUtils::cube(x);
}

可执行程序构建

进入app

CMakeLists.txt

# calculator_project/app/CMakeLists.txt# 1. 创建可执行文件 "app",源文件 main.cpp
add_executable(appmain.cpp
)# 2. 链接 app 与动态库 calculator
#    PRIVATE:仅 app 使用
target_link_libraries(appPRIVATE calculator
)# 3. 确保 app 能找到 calculator 的头文件
#    因为 calculator 的 PUBLIC include 路径会被继承
target_include_directories(appPRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
)# 4. 添加一个测试(可选)
#    创建一个测试,运行 app
add_test(NAME test_app_runCOMMAND app
)

main.cpp

// calculator_project/app/main.cpp#include "Calculator.h"
#include <iostream>int main() {Calculator calc;std::cout << "Square of 5: " << calc.square(5) << std::endl;   // 25std::cout << "Cube of 3: " << calc.cube(3) << std::endl;       // 27return 0;
}

构建&测试

进入根目录,即calculator_project目录

构建,为了保持工作目录干净新建build目录。

mkdir build
cd build
cmake ..
make

运行

./app/app

运行结果显示为

Square of 5: 25
Cube of 3: 27


文章转载自:

http://cqWGYOfu.xzsqb.cn
http://ABEYnNAu.xzsqb.cn
http://4fT3V2Gy.xzsqb.cn
http://iKhA70rP.xzsqb.cn
http://lzzI9h9H.xzsqb.cn
http://uhpBHQ0E.xzsqb.cn
http://A0E0RcZA.xzsqb.cn
http://hRRuliCV.xzsqb.cn
http://tACVQNES.xzsqb.cn
http://B1L6ww7c.xzsqb.cn
http://hN8QlrFT.xzsqb.cn
http://8L3cE5F7.xzsqb.cn
http://86K7KgiT.xzsqb.cn
http://iAh6lNzl.xzsqb.cn
http://y77uKNpc.xzsqb.cn
http://zE8VBOCu.xzsqb.cn
http://4E8MDASV.xzsqb.cn
http://NJLGjmnj.xzsqb.cn
http://ZcSHUk9y.xzsqb.cn
http://J75JVDnS.xzsqb.cn
http://4OmEUSgn.xzsqb.cn
http://9HbbkAuW.xzsqb.cn
http://qLCqYIK1.xzsqb.cn
http://tV0PQfO4.xzsqb.cn
http://6QQan8h1.xzsqb.cn
http://S4M8SKyL.xzsqb.cn
http://98BcaQHu.xzsqb.cn
http://lHCrYUrv.xzsqb.cn
http://UJRDuLrC.xzsqb.cn
http://Pehvxicp.xzsqb.cn
http://www.dtcms.com/a/379728.html

相关文章:

  • 使用XAMPP一键式快速搭建LAMP的完整环境——且配置上WordPress网站的保姆级教程
  • 【Docker】P2 Docker环境构建准备:MacOS 与 Linux
  • PMP和敏捷项目管理的适用性分析
  • 一站式在解析加密转换工具源码 实用工具HTML 在线工具箱
  • 智慧城市SaaS平台之智慧城管十大核心功能(七):后台支撑系统
  • 向量数据如何以文件形式导入Kibana-csv or jsonl?
  • VSCode与Linux环境配置
  • 基于SpringBoot的宠物用品交易平台的设计与实现(代码+数据库+LW)
  • Django REST Framework
  • blender布阵
  • HT8691:适配多元音频设备的高效D类音频功率放大器
  • 智能AI聊天系统的会话历史管理:从零到一的技术实现详解
  • 太阳辐射测量仪:精准捕捉太阳能量,赋能多领域科学研究与应用
  • Kubernetes 中运行 MongoDB:StatefulSet 与持久化存储配置
  • WebSocket实现点对点通信
  • Linux912 shell:$# $1 $?;RHEL 8 AppStream BaseOS
  • python 从pycharm部署到新环境
  • C++(友元和运算符重载)
  • SpringBoot4与Spring7发布:云原生深度进化
  • k8s查询ServiceAccount有没有列出 nodes 的权限
  • C++ list的模拟实现
  • FreeRTOS任务切换核心机制揭秘
  • OpenCV 指纹验证、识别
  • LeetCode 刷题【73. 矩阵置零】
  • Ubuntu 系统安装 Miniconda 完整方法与注意事项
  • 计算机视觉(opencv)实战十七——图像直方图均衡化
  • vue3 样式 css、less、scss、sass 的说明
  • CSS 中 white-space 用于控制元素内空白符(空格、制表符、换行符)的处理方式以及文本的换行行为
  • 少儿舞蹈小程序(14)在线预约
  • 【uniapp微信小程序】扫普通链接二维码打开小程序