c++ CMakeLists.txt详解

news2024/12/12 23:51:27

基本结构

  1. CMake 最低版本声明
    用于指定需要的最低 CMake 版本,确保兼容性。
cmake_minimum_required(VERSION 3.10)
  • 指定 CMake 的最低版本。
  • 确保用户的 CMake 版本符合项目需求,否则报错。
  • 版本选择建议根据项目使用的功能决定。例如,3.10 引入了 target_link_directories
  1. 项目名称和语言定义
    定义项目的名称及支持的编程语言。
project(ProjectName LANGUAGES C CXX)
  • ProjectName:项目名称,自动赋值给变量 ${PROJECT_NAME}
  • LANGUAGES:指定项目支持的语言,可以是 CCXX(C++)、Fortran 等。
  • 默认生成变量:
    • ${PROJECT_SOURCE_DIR}:项目根目录。
    • ${PROJECT_BINARY_DIR}:构建目录。
  1. 设置编译选项
    设置标准版本(如 C++17)或添加额外的编译器选项。
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
  • CMAKE_CXX_STANDARD:设置 C++ 标准(如 11、14、17、20)。
  • CMAKE_CXX_STANDARD_REQUIRED:强制使用指定版本。
  • CMAKE_CXX_EXTENSIONS:是否使用非标准扩展(如 -std=gnu++17)。
  1. 定义源文件和头文件路径
    将源代码组织到变量中,或直接指定路径。
set(SOURCES src/main.cpp src/foo.cpp)
set(INCLUDES include/)
  1. 生成可执行文件或库
    指定目标类型(可执行文件、静态库、动态库)。
# 添加可执行文件
add_executable(MyApp ${SOURCES})

# 添加静态库
add_library(MyStaticLib STATIC src/foo.cpp src/bar.cpp)

# 添加动态库
add_library(MySharedLib SHARED src/foo.cpp src/bar.cpp)
  1. 设置目标的头文件路径
    将头文件目录添加到目标的构建路径中。
target_include_directories(MyApp PRIVATE ${INCLUDES})
  1. 链接内部库
    链接外部依赖库或内部生成的库。
target_link_libraries(MyApp PRIVATE MyLib)
  1. 查找外部库(可选)
    查找并使用外部库(如 Boost 或 OpenCV)。
find_package(OpenCV REQUIRED)
target_link_libraries(MyApp PRIVATE ${OpenCV_LIBS})
  1. 安装规则
    指定生成的二进制文件、配置文件等的安装路径。
install(TARGETS MyApp DESTINATION bin)
install(FILES config/settings.conf DESTINATION etc)
  • install() 定义安装文件的位置。
  • 常见用途:
    • 安装可执行文件到 bin
    • 安装库到 lib
    • 安装配置文件到 etc
  1. 测试支持(可选)
    启用单元测试功能。
enable_testing()
add_test(NAME MyTest COMMAND MyApp --test)
  1. 子目录管理(可选)
    用于大型项目,将多个模块分割到不同的子目录。
add_subdirectory(src/module1)
  • 对于大型项目,将代码分割到子目录中,通过 add_subdirectory() 引入。

子模块的 CMakeLists.txt

add_library(Module1 STATIC module1.cpp)
target_include_directories(Module1 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
  1. 添加自定义命令和目标(可选)
  • 添加自定义命令
add_custom_command(
    OUTPUT generated.cpp
    COMMAND python generate.py > generated.cpp
    DEPENDS generate.py
)
  • 添加自定义目标
add_custom_target(GenerateCode ALL DEPENDS generated.cpp)
  1. 使用变量和条件(动态配置)
  • 条件语句
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
    message("Debug build")
endif()
  • 变量替换
set(VERSION "1.0.0")
message("Project version: ${VERSION}")

示例1:单模块(c++)

项目结构

MyProject/
├── CMakeLists.txt
├── src/
│   ├── main.cpp
│   ├── foo.cpp
├── include/
│   └── foo.h
└── config/
    └── settings.conf

代码文件

  • src/main.cpp:
#include <iostream>
#include "foo.h"

int main() {
    std::cout << "Sum of 3 and 5 is: " << add(3, 5) << std::endl;
    return 0;
}
  • src/foo.cpp:
#include "foo.h"

int add(int a, int b) {
    return a + b;
}
  • include/foo.h:
#ifndef FOO_H
#define FOO_H

int add(int a, int b);

#endif
  • config/settings.conf:
# This is a placeholder configuration file

CMakelist.txt

# 设置 CMake 最低版本
cmake_minimum_required(VERSION 3.10)

# 定义项目名称和语言
project(MyProject LANGUAGES CXX)

# 设置编译选项
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# 定义源文件和头文件目录
set(SOURCES
    src/main.cpp
    src/foo.cpp
)

set(INCLUDES
    include/
)

# 添加可执行目标
add_executable(MyApp ${SOURCES})

# 配置头文件路径
target_include_directories(MyApp PRIVATE ${INCLUDES})

# 安装规则
install(TARGETS MyApp DESTINATION bin)
install(FILES config/settings.conf DESTINATION etc)

# 启用测试支持
enable_testing()
add_test(NAME RunTests COMMAND MyApp)

构建和运行

1. 创建构建目录

为了保持源文件清晰,推荐在源代码目录外创建构建目录:

mkdir build
cd build

2. 运行 CMake

使用 CMake 生成构建文件:

cmake ..

3. 编译项目

使用 CMake 的构建命令:

cmake --build .

4. 运行程序

./MyApp

5. 安装程序

将可执行文件和配置文件安装到指定目录:

cmake --install .

示例2:多模块(c++)

项目结构

MyProject/
├── CMakeLists.txt         # 顶层 CMakeLists.txt
├── module1/               # 模块1
│   ├── CMakeLists.txt     # 模块1的 CMakeLists.txt
│   ├── module1.cpp
│   └── module1.h
├── module2/               # 模块2
│   ├── CMakeLists.txt     # 模块2的 CMakeLists.txt
│   ├── module2.cpp
│   └── module2.h
├── app/                   # 主程序
│   ├── CMakeLists.txt     # 主程序的 CMakeLists.txt
│   ├── main.cpp
└── build/                 # 构建目录

顶层 CMakeLists.txt

顶层的 CMakeLists.txt 文件负责整体项目的配置,包括引入各个模块、设置编译选项以及定义最终的构建目标。

# 设置最低 CMake 版本
cmake_minimum_required(VERSION 3.10)

# 定义项目名称和语言
project(MyProject LANGUAGES CXX)

# 设置编译选项
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# 添加子模块目录
add_subdirectory(module1)
add_subdirectory(module2)
add_subdirectory(app)

模块1的 CMakeLists.txt

模块1构建为一个静态库,提供对其他模块的功能支持。

# 定义模块1的库
add_library(Module1 STATIC module1.cpp)

# 指定模块1的头文件路径
target_include_directories(Module1 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

# 可选:设置特定的编译选项(如果模块需要)
target_compile_options(Module1 PRIVATE -Wall -Wextra)

模块2的 CMakeLists.txt

模块2构建为一个动态库,并依赖模块1。

# 定义模块2的库
add_library(Module2 SHARED module2.cpp)

# 指定模块2的头文件路径
target_include_directories(Module2 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

# 链接模块1
target_link_libraries(Module2 PUBLIC Module1)

主程序的 CMakeLists.txt

主程序依赖模块1和模块2,并最终生成可执行文件。

# 定义主程序的可执行目标
add_executable(MyApp main.cpp)

# 链接模块1和模块2
target_link_libraries(MyApp PRIVATE Module1 Module2)

# 指定主程序的头文件路径(如果需要)
target_include_directories(MyApp PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})

示例代码

  • module1/module1.h
#ifndef MODULE1_H
#define MODULE1_H

int add(int a, int b);

#endif
  • module1/module1.cpp
#include "module1.h"

int add(int a, int b) {
    return a + b;
}
  • module2/module2.h
#ifndef MODULE2_H
#define MODULE2_H

int multiply(int a, int b);

#endif
  • module2/module2.cpp
#include "module2.h"
#include "module1.h"

int multiply(int a, int b) {
    return a * add(a, b);  // 使用模块1的功能
}
  • app/main.cpp
#include <iostream>
#include "module1.h"
#include "module2.h"

int main() {
    int a = 3, b = 5;
    std::cout << "Add: " << add(a, b) << std::endl;
    std::cout << "Multiply: " << multiply(a, b) << std::endl;
    return 0;
}

功能扩展

  • 模块化管理: 将子模块组织到不同目录,并通过 add_subdirectory() 引入。

  • 外部库集成: 使用 find_package()target_link_libraries() 管理外部库。

  • 生成静态库: 使用 add_library() 定义静态库目标,并链接到其他可执行文件。

  • 跨平台支持: CMake 支持跨平台构建(如 Makefile、Visual Studio 项目文件等)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2258477.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

轮转数组

轮转数组 1、题目描述2、解答思路2.1、辅助数组2.2、原地反转 1、题目描述 给定一个整数数组 nums&#xff0c;将数组中的元素向右轮转 k 个位置&#xff0c;其中 k 是非负数。 2、解答思路 2.1、辅助数组 如果我们在原数组上通过覆盖元素会导致部分元素的丢失&#xff0c…

如何编译安装系统settings设置应用(5.0.0-Release)

本文介绍如何在OpenHarmony 5.0.0 r版本中修改系统设置应用&#xff0c;并且编译安装到开发板上 开发环境 1.dayu200开发板 2.OpenHarmony 5.0.0r 固件 3.API12 full sdk &#xff08;如果安装full sdk过程中出现报错hvigor ERROR: Cannot find module typescript,请参考 h…

学习记录,隐式对象,隐式类

隐式对象 格式&#xff1a;就是在对象前面加一个 implicit 作用&#xff1a;就是给函数当默认值&#xff01; 隐式类 隐式类 一个类 一个隐式转换函数 格式&#xff1a;在class 的前面&#xff0c;添加implicit 要点&#xff1a;要有一个参数&#xff0c;就要待被转换的类型…

第三部分:进阶概念 9.错误处理 --[JavaScript 新手村:开启编程之旅的第一步]

在JavaScript中&#xff0c;错误处理是确保应用程序稳定性和用户体验的重要部分。JavaScript提供了几种机制来捕获和处理运行时错误&#xff08;异常&#xff09;。以下是几种常见的错误处理方式&#xff1a; 1. try...catch 语句 try...catch 语句是JavaScript中处理错误和异…

Java面试之多线程状态(三)

此篇接上一篇Java面试之实现多线程(二) Java线程可以拥有自己的操作数栈、程序计数器、局部变量表等资源&#xff0c;它与同一进程内的其他线程共享该进程的所有资源。Java线程在生命周期内存在多种状态&#xff0c;可以通过Thread.State枚举类获取线程状态。如图所示有NEW(新建…

数据仓库:智控数据中枢

数据仓库 一. 什么是数据仓库&#xff1f;二. 传统数据库与数据仓库的区别&#xff1f;三. 数据仓库详解&#xff08;一&#xff09;. 数据分析&#xff08;二&#xff09;. 特点1. 面向主题2. 集成的3. 反应历史变化 四. 如何搭建数据仓库&#xff08;一&#xff09;. 数据平台…

【全连接神经网络】核心步骤及其缺陷

前向传播 计算公式&#xff08;其中一种&#xff09; x1/x2&#xff1a;输入值&#xff0c;一般是神经网络上一层的输出或者输入数据本身&#xff0c;上图中表示两个节点w11 w13&#xff1a;权重&#xff0c;在神经网络中&#xff0c;权重是学习的参数&#xff0c;表示每个输入…

微服务的问题

1.创建maven项目 然后配置对应的maven地址 2.创建父工程 删掉其中的src文件 在父pom中进行版本依赖和管理 如下图所示 3.在子文件中进行添加依赖 然后刷新maven进行下载

CAPL如何设置或修改CANoe TCP/IP协议栈的底层配置

在CANoe中创建网络节点作为以太网主机时,可以给其配置独立的TCP/IP Stack。 配置的协议栈有一些底层配置参数可以在界面上设置或修改,比如: MTU上图中MTU显示500只是图形界面显示错误,正确值是1500。 TCP延迟确认这些参数也可以通过CAPL动态配置,甚至CAPL还可以配置很多界…

计算机视觉与医学的结合:推动医学领域研究的新机遇

目录 引言医学领域面临的发文难题计算机视觉与医学的结合&#xff1a;发展趋势计算机视觉结合医学的研究方向高区位参考文章结语 引言 计算机视觉&#xff08;Computer Vision, CV&#xff09;技术作为人工智能的重要分支&#xff0c;已经在多个领域取得了显著的应用成果&…

微搭低代码AI组件单词消消乐从0到1实践

目录 1 为什么要开发单词消消乐2 需要具备什么功能3 采用什么技术方案实现4 逻辑设计4.1 数据结构设计4.2 游戏的核心逻辑4.3 数据设计 5 代码详解5.1 导入依赖5.2 定义函数组件5.3 数据初始化5.4 状态定义5.5 打乱解释的逻辑5.6 定义选择单词的函数5.7 定义选择解释的函数5.8 …

learn-(Uni-app)输入框u-search父子组件与input输入框(防抖与搜索触发)

1.父子组件u-search &#xff08;1&#xff09;父组件 <!-- 父组件 --> <template> <div><searchBar change"change" search"search"></searchBar> </div> </template> <script> // 子组件搜索 import…

SpringBoot【九】mybatis-plus之自定义sql零基础教学!

一、前言&#x1f525; 环境说明&#xff1a;Windows10 Idea2021.3.2 Jdk1.8 SpringBoot 2.3.1.RELEASE mybatis-plus的基本使用&#xff0c;前两期基本讲的差不多&#xff0c;够日常使用&#xff0c;但是有的小伙伴可能就会抱怨了&#xff0c;若是遇到业务逻辑比较复杂的sq…

electron 打包 webview 嵌入需要调用电脑摄像头拍摄失败问题

electron 打包 webview 嵌入需要调用电脑摄像头拍摄失败问题 这篇文章是接我cocos专栏的上一篇文章继续写的&#xff0c;我上一篇文章写的是 cocos 开发触摸屏项目&#xff0c;需要嵌入一个网页用来展示&#xff0c;最后通过 electron 打包成 exe 程序&#xff0c;而且网页里面…

webrtc学习----前端推流拉流,局域网socket版,一对一

提示&#xff1a;局域网socket版 文章目录 [TOC](文章目录) 前言一、教程二、webrtc工作流程三、推流端四、拉流五、socket服务六、效果七、备注总结 前言 ‌‌‌‌‌WebRTC&#xff08;Web Real-Time Communication&#xff09;‌是一种实时通讯技术&#xff0c;允许网络应用或…

net/http: TLS handshake timeout 问题

最近系统偶现”net/http: TLS handshake timeout“&#xff0c;而且都集中在同一个机房&#xff0c;这个报错还是第一次见&#xff0c;产生的原因和解决的方案都比较有意思。 现场 报错的信息为&#xff1a; Error sending request:%!(EXTRA *url.ErrorGet "https://**…

HTML简单贪吃蛇游戏

1.功能说明&#xff1a; 游戏网格&#xff1a;一个20x20的网格&#xff0c;每个格子的大小为20x20像素。 蛇的移动&#xff1a;玩家可以通过方向键&#xff08;左、上、右、下&#xff09;控制蛇的移动。 食物生成&#xff1a;食物会在随机位置生成&#xff0c;当蛇吃到食物时…

http 502 和 504 的区别

首先看一下概念&#xff1a; 502&#xff1a;作为网关或者代理工作的服务器尝试执行请求时&#xff0c;从上游服务器接收到无效的响应。503&#xff1a;由于临时的服务器维护或者过载&#xff0c;服务器当前无法处理请求。这个状况是临时的&#xff0c;并且将在一段时间以后恢…

基于SpringBoot医疗挂号系统(计算机毕业设计)+万字说明文档

系统合集跳转 源码获取链接 一、系统环境 运行环境: 最好是java jdk 1.8&#xff0c;我们在这个平台上运行的。其他版本理论上也可以。 IDE环境&#xff1a; Eclipse,Myeclipse,IDEA或者Spring Tool Suite都可以 tomcat环境&#xff1a; Tomcat 7.x,8.x,9.x版本均可 操作系统…

【青牛科技】D4800 AB类 立 体 声 耳 机 音 频 功 率 放 大器电路可应用在便携式数字 音 响 设 备 中 作 功 率 放 大 用

概 述 &#xff1a; D4800 是 一 块 AB类 立 体 声 耳 机 音 频 功 率 放 大器电路。 D4800 在5V电 源 时 输 出 功 率 最 高 可 达 290mW(8 Ω 负载&#xff0c; 失真度 10%)。适合在便携式数字 音 响 设 备 中 作 功 率 放 大 用 。 主要特点&#xff1a; 电源电压&#x…