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

cmake 编译教程

参考链接:cmake使用详细教程(日常使用这一篇就足够了)_cmake教程-CSDN博客

 一、只有一个源文件的程序编译

首先在当前目录下创建两个文件
hello.cpp
CMakeLists.txt (注意CMakeLists大小写,不要写错了)
cmake_minimum_required (VERSION 2.8)project (learn_cmake)add_executable(hello hello.cpp)
  • 第一行意思是cmake最低版本要求2.8,
  • 第二行是本项目的工程名
  • 第三行:第一个变量:要生成的可执行文件名为hello,后面的参数是需要的依赖。
接着在当前目录下执行 cmake . 接着会发现目录下多生成了一些文件,例如Makefile,然后使用GNU make命令来编译程序,会生成可执行程序。

二、同一目录下多个源文件

此时在当前目录新增两个依赖,并mian函数的执行需要依赖这两个文件

add.cpp

add.h

只需要在CMakeLists.txt中添加所依赖的.cpp文件,编译步骤和上面相同。

cmake_minimum_required (VERSION 2.8)project (learn_cmake)add_executable(hello hello.cpp myadd.cpp)

三、同一目录下很多源文件


如果同一目录下有无穷多源文件,那么一个一个添加就很慢了。此时可以使用cmake中的函数存储这些源文件

aux_source_directory(dir var)

他的作用是把dir目录中的所有源文件都储存在var变量中

然后需要用到源文件的地方用 变量var来取代

此时 CMakeLists.txt 可以这样优化

cmake_minimum_required(VERSION 2.8)project(learn_cmake)aux_source_directory(. SRC_LIST)add_executable(hello ${SRC_LIST})

四、头文件在别的文件夹

对于集中的头文件,CMake提供了一个很方便的函数

include_directories ( dir )

他的作用是 自动去dir目录下寻找头文件,相当于 gcc中的 gcc -I dir

此时 CMakeLists.txt 可以这样优化

cmake_minimum_required(VERSION 2.8)project(learn_cmake)aux_source_directory(. SRC_LIST)include_directories(./inc_dir)add_executable(hello ${SRC_LIST})

 五、头文件源文件分离,并含有多个文件夹

假如说当前的工程目录是这样的,头文件和源文件分离,并含有多个文件夹

此时 CMakeLists.txt 可以这样优化

cmake_minimum_required(VERSION 2.8)project(learn_cmake)aux_source_directory(src_dir1 SRC_LIST1)
aux_source_directory(src_dir2 SRC_LIST2)
aux_source_directory(main_dir MAIN_DIR)include_directories(./inc_dir1 ./inc_dir2)add_executable(hello ${SRC_LIST1} ${SRC_LIST2} ${MAIN_DIR})

六、生成动态库和静态库

假如说当前的项目目录是这样的

  • inc目录下存放头文件
  • src目录下存放源文件
  • lib目录下存放生成的库
  • build目录下存放构建项目相关的文件,如CMakeLists.txt。而稍后我们也在这个目录下执行cmake和make

 

 此时 CMakeLists.txt 可以这样优化

cmake_minimum_required(VERSION 2.8)project(learn_lib)#整合源文件
aux_source_directory(${PROJECT_BINARY_DIR}/../src SRC_LIST)#引入头文件路径
include_directories(${PROJECT_BINARY_DIR}/../inc)#生成静态库或者动态库 参数1:生成的库的名称 参数2:静态或动态 参数3:生成库所需要的源文件
add_library(func_shared SHARED ${SRC_LIST})
add_library(func_static STATIC ${SRC_LIST})#设置最终生成的库的名称
set_target_properties(func_shared PROPERTIES OUTPUT_NAME "myfunc")
set_target_properties(func_static PROPERTIES OUTPUT_NAME "myfunc")#设置生成的库的路径
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/../lib)

开始编译:

  1. 在build目录下执行 cmake .
  2. 在build目录下执行 make
  3. 查看lib目录下是否生成库文件,

出现库文件就算编译成功

七、链接库文件

库文件目录结构如下:

  • lib目录下存放静态库和动态库
  • main_src目录下存放main函数相关的源文件
  • bin目录存放项目生成的可执行文件

 此时 CMakeLists.txt 可以这样写

cmake_minimum_required(VERSION 2.8)project(learn_lib)#整合源文件
aux_source_directory(${PROJECT_BINARY_DIR}/../main_src MAIN_SRC)#引入头文件路径
include_directories(${PROJECT_BINARY_DIR}/../inc)#生成静态库或者动态库 参数1:生成的库的名称 参数2:静态或动态 参数3:生成库所需要的源文件
add_library(func_shared SHARED ${SRC_LIST})
add_library(func_static STATIC ${SRC_LIST})#设置最终生成的库的名称
set_target_properties(func_shared PROPERTIES OUTPUT_NAME "myfunc")
set_target_properties(func_static PROPERTIES OUTPUT_NAME "myfunc")#设置生成的库的路径
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/../lib)#查找库文件 第一个参数:存储查找到的库文件 第二个参数:要查找的库文件 第三个参数:要查找的目录
find_library(FUNC_LIB myfunc ${PROJECT_BINARY_DIR}/../lib)#设置可执行文件生成到哪里
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/../bin)add_executable(hello ${MAIN_SRC})target_link_libraries(hello ${FUNC_LIB})

八、如何选择动态库和静态库

选择生成动态库(Dynamic Link Library,DLL 在 Windows 上,Shared Object,.so 在 Unix/Linux 上,或 Dynamic Library,.dylib 在 macOS 上)还是静态库(Library Archive,.a 或 .lib)主要取决于以下几个因素:

动态库的优点:

  1. 资源占用: 动态库在多个程序间共享相同的代码,可以节省系统内存和磁盘空间,因为不需要为每个使用该库的应用程序复制整个库。
  2. 更新方便: 更新动态库时,所有依赖它的应用程序都会自动使用新版本,无需重新编译或分发应用程序。
  3. 模块化: 动态库可以更容易地实现模块化编程,允许在运行时加载或卸载库,增强程序的灵活性和扩展性。
  4. 性能: 尽管启动时可能需要一些额外的时间来解析动态库中的符号,但在频繁调用的情况下,动态链接可能会更快,因为它避免了静态链接中的冗余代码。

静态库的优点:

  1. 部署简单: 使用静态库的程序是自包含的,不需要在目标机器上存在额外的库文件。
  2. 可靠性: 不会受到“依赖地狱”问题的影响,即不会因为缺少动态库或者动态库版本不匹配而导致程序崩溃。
  3. 安全性: 避免了由于动态库被恶意替换而导致的安全风险。
  4. 兼容性: 特别是在嵌入式系统或资源受限的环境中,静态链接可以确保软件的完整性和最小化依赖。

选择策略:

  • 如果库的使用者需要减少最终可执行文件的分发复杂度,或者目标平台资源有限,静态库可能是更好的选择。
  • 如果库需要在多个应用之间共享,或者希望简化库的更新流程,动态库更为合适。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 编程-设计模式 23:模板方法模式
  • mfc140u.dll丢失的科学修复手段,简单又方便的mfc140u.dll修复
  • Ant-Design-Vue快速上手指南+排坑
  • 前端八股文笔记【三】
  • 前端(react)框架nextjs
  • C++ 数组 -- 指针 -- 字符串
  • 【系统分析师论文】论系统需求分析方法及应用
  • 【wiki知识库】09.欢迎页面展示(浏览量统计)SpringBoot部分
  • 【MySQL】视图——视图、视图的概念、为什么要使用视图、视图的基本使用、视图规则和限制
  • 如何在linux系统上部署nginx
  • 动态规划之——背包DP(完结篇)
  • 【redis】redis 消息队列学习
  • 分布式数据库的原理、发展历史与技术特点
  • LLM - 使用 HuggingFace + Ollama 部署最新大模型 (GGUF 格式 与 Llama 3.1)
  • openssl 制作 信用库与服务证书
  • 【技术性】Search知识
  • express + mock 让前后台并行开发
  • Java教程_软件开发基础
  • Markdown 语法简单说明
  • Perseus-BERT——业内性能极致优化的BERT训练方案
  • PHP 程序员也能做的 Java 开发 30分钟使用 netty 轻松打造一个高性能 websocket 服务...
  • PHP 的 SAPI 是个什么东西
  • php的插入排序,通过双层for循环
  • Spring Boot快速入门(一):Hello Spring Boot
  • 不发不行!Netty集成文字图片聊天室外加TCP/IP软硬件通信
  • 前端技术周刊 2019-01-14:客户端存储
  • 前言-如何学习区块链
  • 如何使用 JavaScript 解析 URL
  • 使用putty远程连接linux
  • 项目实战-Api的解决方案
  • 学习使用ExpressJS 4.0中的新Router
  • 鱼骨图 - 如何绘制?
  • MiKTeX could not find the script engine ‘perl.exe‘ which is required to execute ‘latexmk‘.
  • gunicorn工作原理
  • ​iOS实时查看App运行日志
  • ‌前端列表展示1000条大量数据时,后端通常需要进行一定的处理。‌
  • # Python csv、xlsx、json、二进制(MP3) 文件读写基本使用
  • #### go map 底层结构 ####
  • #Datawhale AI夏令营第4期#AIGC方向 文生图 Task2
  • #周末课堂# 【Linux + JVM + Mysql高级性能优化班】(火热报名中~~~)
  • (14)Hive调优——合并小文件
  • (2.2w字)前端单元测试之Jest详解篇
  • (2022 CVPR) Unbiased Teacher v2
  • (Java数据结构)ArrayList
  • (Matalb回归预测)PSO-BP粒子群算法优化BP神经网络的多维回归预测
  • (附源码)ssm跨平台教学系统 毕业设计 280843
  • (教学思路 C#之类三)方法参数类型(ref、out、parmas)
  • (力扣题库)跳跃游戏II(c++)
  • (一)pytest自动化测试框架之生成测试报告(mac系统)
  • (转)关于多人操作数据的处理策略
  • (转)真正的中国天气api接口xml,json(求加精) ...
  • (转载)PyTorch代码规范最佳实践和样式指南
  • . NET自动找可写目录
  • .dwp和.webpart的区别
  • .NET Core 2.1路线图