cmake原理

CMake原理与快速入门

CMake是一个跨平台构建(build)工具,完成代码编译链接打包过程。在开发AI应用平台时,由于开发的平台是在边缘设备运行的,而边缘设备的算力不高,所以对平台的效率要求比较高,都是优先使用C++开发的。

在C++开发中,CMake是不可或缺的,与CMake类似的工具有微软的MSBuild(在Visual Studio中使用)、安卓开发的Gradle(Android Studio)。

上图是c/cpp的编译流程:编译cpp时是以单个文件为单位,每个cpp文件会得到一个.o的文件,里面包含了机器可以执行的代码。有多个文件的时候,会用到其它头文件里定义的函数,而编译这个cpp时编译器是不知道要调用的函数地址是什么,所以会暂时设置为0,直到链接过程才会修正。

随着项目的复杂化,编译的.cpp和.h文件越来越多,这个编译和链接的过程也越来越复杂,于是make工具(Makefile)出现了,这个古老的技术(1977)可以帮助我们构建一颗依赖树,然后通过make命令来递归执行构建。

在这里插入图片描述

然而,随着项目变得更复杂,Makefile也变得繁杂了起来,而且对于不同平台,要写的Makefile还不一样,于是cmake出现了。CMake可以通过CMakeLists.txt来生成makefile来给make用。

快速例子

CMake依赖于CMakeLists.txt这个文本文件。

# 使用`#`来注释文件
# 这一行表示cmake的最低版本
cmake_minimum_required(VERSION 3.10)
# 项目名称,输出的文件就叫这个名字
project(Example)
# 项目Example需要构建可执行文件,由main.cpp编译得到
add_executable(Example main.cpp)

有了CMakeLists.txt之后,CMake需要根据编译平台进行配置(Configure),然后进行build。

build直接使用cmake build即可。

CMake参数和命令

  • add_executable

    就是为项目添加所有的源代码,可以无限加

    add_executable(Example main.cpp my1.cpp my2.cpp my3.cpp)
    
  • aux_source_directory(dir var)

    glob操作,将dir下的所有源文件存到var变量中,后续通过${var}进行调用

    aux_source_directory(. SRC_LIST)
    add_executable(Example ${SRC_LIST})
    
  • include_directories(dir)

    之前是编译cpp文件,假如定义和实现分开,你有很多头文件,则可以让cmake自动去dir下寻找头文件(也可以多个目录)

    include_directories(./include1 ./include1)
    
  • add_library(lib_name STATIC/SHARED src)

    生成静态库或者动态库,和add_executable的用法类似。

    # 第一个参数是生成的库的名称 第二个是动态或者静态 后面是源文件
    add_library(func_shared SHARED ${SRC_LIST})
    add_library(func_shared STATIC ${SRC_LIST})
    
  • set_target_properties()

    设置目标的属性,一般可以用来设置版本号和输出名称

    # 更改输出文件名
    # 将 hello_static 更名为 hello
    SET_TARGET_PROPERTIES (hello_static PROPERTIES OUTPUT_NAME "hello")# 设置版本号
    # 将hello的动态库版本设置为1.2 API版本设置为1
    SET_TARGET_PROPERTIES (hello PROPERTIES VERSION 1.2 SOVERSION 1)
    
  • set

    用来定义或者修改变量的值,这些变量可以是普通变量、缓存变量或环境变量。

    # EXECUTABLE_OUTPUT_PATH是系统变量,这里设置可执行文件的输出目录到bin下
    set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/../bin)
    # LIBRARY_OUTPUT_PATH是系统变量,这里设置链接库的输出目录到lib下
    set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/../lib)
    
  • find_library(var lib_name lib_path1 lib_path2)

    在lib_path路径下查找库(.so .a),并存到var变量

    # 将库myfunc的位置存到FUNC_LIB中
    find_library(FUNC_LIB myfunc ${PROJECT_BINARY_DIR}/../lib)
    
  • target_link_libraries(target lib_name)

    用来把lib连接到一个可执行文件中

    # 上一步找到的库连接到可执行文件
    target_link_libraries(hello ${FUNC_LIB})
    
  • find_package

    从计算机上寻找库,寻找到的库会保存XXX_FOUND/_DIR/_INCLUDE_DIR/_LIBS等变量。REQUIRED表示必须要找到package,否则报错。

    # 找OpenCV
    find_package(OpenCV REQUIRED)
    # 接下来可以使用这些路径了
    ${OpenCV_DIR}
    ${OpenCV_INCLUDE_DIRS}
    ${OpenCV_LIBS}
    # 也可以进行一些逻辑控制(if中直接用变量名)
    if(OpenCV_FOUND)target_link_libraries(...)
    else(OpenCV_FOUND)message(FATAL_ERROR ”GLOG library not found”)
    endif(OpenCV_FOUND)
    
  • 常用变量

    PROJECT_BINARY_DIR:cmake配置命令的目录,通常是build目录下。

    PROJECT_SOURCE_DIR:代码的路径

    通常假如源码路径是src,那么在src下创建一个build,再进入build,然后cmake ..,表示build的上一级是源码,但是编译结果保存在build下。

常用编译流程

rm -rf build  # 删除旧的build,假如没有旧的或者makefile没有变化,则不需要这一步
mkdir build
cd build
cmake ..      # 根据CMakeLists.txt生成makefile
make          # 根据txt生成makefile进行编译make clean    # 不一定需要,删除make之前生成的缓存

参考:

【软件构建: CMake 快速入门】 https://www.bilibili.com/video/BV1rR4y1E7n9/?share_source=copy_web&vd_source=cdc2983e744e85d26061233640e163f4

【cmake学习】set_target_properties 常见属性以及获取target 属性_set——target-CSDN博客

CMake,make,CMakeLists.txt,CMakeFiles之间的关系_.cmake .cmake.in cmakefile.txt 的关系-CSDN博客

【隐藏的细节:编译与链接】 https://www.bilibili.com/video/BV1TN4y1375q/?share_source=copy_web&vd_source=cdc2983e744e85d26061233640e163f4
2911202/article/details/85337968)

【隐藏的细节:编译与链接】 https://www.bilibili.com/video/BV1TN4y1375q/?share_source=copy_web&vd_source=cdc2983e744e85d26061233640e163f4

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

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

相关文章

SFTP全解析:深入了解组件功能与适用场景

文章目录 一、组件功能二、适用场景三、SFTP优势四、SFTP原理五.SFTP与同类产品对比六、部署方案1.裸金属部署2.k8s容器化部署 七、高可用方案八、监控方案九、常见问题及解决方法 一、组件功能 安全文件传输协议SFTP(SSH File Transfer Protocol)是文件传输协议(F…

Android 中文文件名排序实现案例教程

Android 中文文件名排序实现案例教程 一、问题分析二、解决方法2.1 使用系统提供的 Collator 类2.2 使用第三方库 Pinyin4J2.3 自定义排序规则 三、总结 在 Android 应用中,经常需要对包含中文的文件名进行排序。由于中文的特殊性,直接使用字符串比较的方…

java——Spring MVC的工作流程

Spring MVC的工作流程是基于模型-视图-控制器(MVC)设计模式的一个典型实现,以下是其主要工作流程步骤: 客户端请求提交: 用户通过浏览器向服务器发送请求,该请求首先到达Spring MVC的前端控制器DispatcherS…

Mutex::Autolock 和 std::lock_guard 的区别

Mutex::Autolock 和 std::lock_guard 都是 C 中用于管理互斥锁(mutex)的一种方式,它们的目标是自动获取和释放锁,避免手动管理锁的复杂性,从而防止死锁和遗漏解锁等问题。尽管它们有相似的功能,但二者也存在…

<项目代码>YOLOv8 红绿灯识别<目标检测>

YOLOv8是一种单阶段(one-stage)检测算法,它将目标检测问题转化为一个回归问题,能够在一次前向传播过程中同时完成目标的分类和定位任务。相较于两阶段检测算法(如Faster R-CNN),YOLOv8具有更高的…

mac下安装Ollama + Open WebUI + Llama3.1

本文介绍mac下安装Ollama Open WebUI Llama3.1 8b具体步骤。 目录 推荐配置Ollama Open WebUI Llama3.1简介安装Ollama安装Open WebUI 推荐配置 m1以上芯片,16g内存,20g以上硬盘空间 Ollama Open WebUI Llama3.1简介 Ollama: 下载,管理…

Linux 无图形界面磁盘空间排查与优化实践20241127

Linux 无图形界面磁盘空间排查与优化实践 引言:磁盘空间问题的痛点与挑战 🔍 常见问题 当系统磁盘空间超过 90% 时,不仅可能导致性能下降,还可能让关键操作无法正常完成。这种情况下,如何高效且精准地排查磁盘占用来…

【Fargo】27:ffmpeg ffprobe 和python分析h264文件并绘制

从帧和包两个层面进行分析。帧级别分析 ffprobe 可以读取264文件信息 -Y9KP MINGW64 /d/XTRANS/thunderbolt/ayame/zhb-bifrost/player-only (main) $ ffprobe test.h264 ffprobe version N-116778-g7e4784e40c-20240827 Copyright (c) 2007-2024 the FFmpeg developersbuilt …

uniapp生命周期:应用生命周期和页面生命周期

文章目录 1.应用的生命周期2.页面的生命周期 1.应用的生命周期 生命周期的概念:一个对象从创建、运行、销毁的整个过程被称为生命周期 生命周期函数:在生命周期中每个阶段会伴随着每一个函数的出发,这些函数被称为生命周期函数 所有页面都…

【AI】JetsonNano启动时报错:soctherm OC ALARM

1、问题描述 将JetsonNano烧写SD卡镜像为Ubuntu20.04后,启动时报错:soctherm OC ALARM,启动失败;然后系统一直重启 2、原因分析 “soctherm OC ALARM”是检测到系统温度超过安全阈值时发出的过热警告。 “soctherm”代表系统…

SycoTec 4060 ER-S德国高精密主轴电机如何支持模具的自动化加工?

SycoTec 4060 ER-S高速电主轴在模具自动化加工中的支持体现在以下几个关键方面: 1.高精度与稳定性:SycoTec 4060 ER-S锥面跳动小于1微米,确保了加工过程中的极高精度,这对于模具的复杂几何形状和严格公差要求至关重要。高精度加工…

构建一个去中心化的零售生态参与者的商业模型

在数字化和去中心化技术快速发展的背景下,传统零售行业正迎来革命性的转型。去中心化零售生态不仅让消费者、商家和内容创作者在同一平台上共同参与价值的创造和分配,还推动了零售体验、数据控制和社会互动的彻底变革。本文将探讨如何构建一个去中心化的…

clickhouse 使用global in 优化 in查询

文章目录 in例子使用global in in例子 SELECT uniq(UserID) FROM distributed_table WHERE CounterID 101500 AND UserID IN (SELECT UserID FROM distributed_table WHERE CounterID 34)对于in 查询来说,本来查询的就是分布式表,假设这个表有100 个…

Docker 启动和停止的精准掌舵:操控指南

Docker 启动和停止的精准掌舵:操控指南 Docker是一个开源的应用容器引擎,基于Go语言开发,能够让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化。Do…

Oracle Universal Unique Identifier (UUID)

本文介绍Oracle生成全局唯一ID的函数SYS_GUID,后续会对SYS_GUID和Sequence两种方法进行比较。 SYS_GUID 函数生成并返回一个由 16 个字节组成的全局唯一标识符(RAW 值)。在大多数平台上,生成的标识符由主机标识符、调用该函数的进…

微信小程序页面配置详解:从入门到精通

微信小程序页面配置详解:从入门到精通 引言 随着移动互联网的飞速发展,微信小程序作为一种新兴的应用形式,因其便捷性和丰富的功能而受到广泛欢迎。在小程序的开发过程中,页面配置是至关重要的一环。本文将深入探讨微信小程序的页面配置,帮助开发者从基础到高级逐步掌握…

d3-contour 生成等高线图

D3.js 是一个强大的 JavaScript 库,用于创建动态、交互式数据可视化。d3-contour 是 D3.js 的一个扩展模块,用于生成等高线图(contour plots)。 属性和方法 属性 x: 一个函数,用于从数据点中提取 x 坐标。y: 一个函…

Vue 中 data 属性为函数的深度剖析:原理、区别与实践

在 Vue.js 中,data 属性通常是一个 函数 而不是一个对象,这背后有一系列设计上的原因和原理,尤其是与 Vue 的组件系统、实例化机制、以及响应式数据的管理有关。下面我将详细解答这个问题,并结合实际项目示例和代码分析,进行全面讲解。 1. Vue 中 data 为什么是一个函数而…

钉钉与企业微信机器人:助力网站定时任务高效实现

钉钉、企业微信机器人在网站定时任务中的应用,主要体现在自动化通知、提醒以及数据处理等方面。 以下是一些具体的应用场景: 1. 自动化通知 项目进度提醒:在蒙特网站所负责的软件开发或网站建设项目中,可以利用机器人设置定时任…

# [Unity] 【游戏开发】Unity开发基础2-Unity脚本编程基础详解

Unity脚本编程是创建互动式游戏体验的核心技能之一。本文将详细讲解Unity脚本编程的基础知识,包括变量和数据类型、程序逻辑、方法等方面,并通过实例展示如何使用这些基本知识完成简单功能的实现。 1. 新建Unity脚本的基本结构 当在Unity中创建一个脚本时,Unity会生成如下基…