从零开始编写一个cmake构建脚本
简介
本文档介绍cmake构建脚本编写,包含的一些主要元素和命名规范。
cmake构建脚本编写步骤
cmake构建工具版本要明确
# 命令名字要小写,这条语句要求构建工具至少需要版本为3.12或以上
cmake_minimum_required (VERSION 3.12)
工程名及库的版本号明确
在编写工程名以及版本号时有几点需要注意:
-
工程名需要大写
-
版本号需要标明主版本号,次版本号以及补丁版本号,如:
project(PROJECT_NAME VERSION 0.0.0)
PROJECT_NAME工程的版本号时 0.0.0,该版本号会被三个cmake内置变量所继承,例如主版本号PROJECT_VERSION_MAJOR=0,次版本号PROJECT_VERSION_MINOR=0,补丁版本号PROJECT_VERSION_PATCH=0,后续可以直接使用这三个内置变量来使用库的版本号
配置构建语言
可以自己根据工程配置需要构建的语言,比如CXX表示可以编译C++文件;C表示可以编译c文件;ASM表示可以编译汇编文件
enable_language(CXX C ASM)
配置测试用例可选变量
配置自定义变量,默认不构建测试用例,可以由使用者通过传入参数打开测试用例构建选项。
option(BUILD_SAMPLE "Build tests" OFF) # 变量名BUILD_SAMPLE 变量说明"Build tests" 状态 OFF:表示不打开 ON:表示打开
配置打印调试信息
对于一些可能出现的错误或者警告,我们可以通过message
函数给用户输出一些日志信息。
message(WARNING "message text") # 构建时打印警告信息
message(FATAL_ERROR "message text") # 产生CMAKE Error时,会停止编译构建过程
message(STATUS "message text") # 常用于查看变量值,类似于编程语言中的 DEBUG 级别信息.
配置生成动态库或者静态库
配置内置变量BUILD_SHARED_LIBS,设置脚本默认构建库的模式为动态库,用户可以通过传入参数来设置生成的是动态库还是静态库
set(BUILD_SHARED_LIBS TRUE CACHE BOOL "If TRUE, this project is built as a shared library, otherwise as a static library")
常用变量定义
配置一些后面使用比较频繁的变量,变量名需要大写,并且变量名不能以CMAKE开头
set(TARGET_NAME project) # 定义变量存放库名
set(TARGET_SAMPLE_NAME test) # 定义变量存放库测试用例名
set(TARGET_SRC_PATH ${CMAKE_CURRENT_SOURCE_DIR}/${TARGET_NAME}) # 定义变量存放库路径
set(TARGET_SRC ${TARGET_SRC_PATH}/source.cpp) # 定义变量存放库源码
if(BUILD_SAMPLE) # 判断是否需要编译测试用例set(TARGET_SAMPLE_SRC ${TARGET_SRC_PATH}/htmlutil.cpp ${TARGET_SRC_PATH}/main.cpp) # 定义变量存放测试程序源码
endif()
set(TARGET_INCLUDE ${TARGET_SRC_PATH}) # 定义变量存放编译库或编译测试用例所需要的头文件的路径
set(TARGET_INSTALL_INCLUDEDIR include) # 定义变量存放三方库安装时,头文件存放的路径
set(TARGET_INSTALL_BINDIR bin) # 定义变量存放三方库安装时,可执行二进制文件存放的路径
set(TARGET_INSTALL_LIBDIR lib) # 定义变量存放三方库安装时,库存放的路径
引用其他三方库
引用其他三方库的方式有2种
-
引用其他三方库的源码
- 源码有cmake构建脚本,直接通过
add_subdirectory()
引用该三方库
- 源码有cmake构建脚本,直接通过
add_subdirectory(xxx) # xxx是需要引入的三方库源码文件夹名字
- 源码非cmake构建或者无法通过cmake方式构建的,可以将引用三方库的源码添加到本三方库的构建中具体方式
set(SOURCE_NAME source1.cxx source2.cxx ...) # SOURCE_NAME 引入三方库源码变量名称, source1.cxx 引入的源码文件(需要包含文件的路径) add_library(${TARGET_NAME} ${SOURCE_NAME} ...) # TARGET_NAME 本库生成的库名, 通过 add_library 添加 引入三方库源码以及本库源码等生成目标TARGET_NAME
-
引用其他三方库的二进制文件(.so)
- 通过target_link_libraries方法引入,此方法需要指定so的路径:
target_link_libraries(${TARGET_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/XXX) # 引用当前源码路径下的xxx库
- 使用find_package方法来引用,此方法的使用限制参照IDE上find_package使用分析,使用方法:
find_package(XXX REQUIRED) # xxx表示要引入的库名
编译库并配置库的属性
使用target_***的命令为库配置依赖
add_library(${TARGET_NAME} ${TARGET_SRC}) #生成库,会根据内置变量BUILD_SHARED_LIBS变量的值来生成动态库或者静态库
target_include_directories(${TARGET_NAME} PRIVATE ${TARGET_INCLUDE}) #配置构建时所依赖头文件的路径if(BUILD_SHARED_LIBS)set_target_properties(${TARGET_NAME} PROPERTIES VERSION${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH} SOVERSION ${PROJECT_VERSION_MAJOR}) #生成动态库时,为库设置版本号
endif()if(BUILD_SAMPLE)add_executable(${TARGET_SAMPLE_NAME} ${TARGET_SAMPLE_SRC}) #生成测试用例target_include_directories(${TARGET_SAMPLE_NAME} PRIVATE ${TARGET_INCLUDE}) #配置构建时所依赖的头文件路径target_link_libraries(${TARGET_SAMPLE_NAME} PUBLIC ${TARGET_NAME}) #配置所依赖的库
endif()
文件安装
- 支持install,库对外提供被find_package的能力
- install后,所有导出的头文件、动态库、静态库、可执行二进制、cmake文件都可以安装到指定路径下
install(TARGETS ${TARGET_NAME} #TARGETS 安装的目标文件,可以是可执行文件、动态库、静态库EXPORT ${TARGET_NAME} #需要对外导出的文件,该选项用于生成xxxConfig.cmake,便于支持find_packagePUBLIC_HEADER DESTINATION ${TARGET_INSTALL_INCLUDEDIR} #头文件路径PRIVATE_HEADER DESTINATION ${TARGET_INSTALL_INCLUDEDIR} #头文件路径RUNTIME DESTINATION ${TARGET_INSTALL_BINDIR} #可执行程序路径LIBRARY DESTINATION ${TARGET_INSTALL_LIBDIR} #动态库路径ARCHIVE DESTINATION ${TARGET_INSTALL_LIBDIR}) #静态库路径install(FILES ${TARGET_SRC_PATH}/xpath_processor.h #FILES 安装文件,可以是头文件,配置文件等DESTINATION ${TARGET_INSTALL_INCLUDEDIR}/${TARGET_NAME}) # DESTINATION 需要安装到的路径install(EXPORT ${TARGET_NAME}FILE ${TARGET_NAME}Targets.cmake #FILE 安装单个文件 ${TARGET_NAME}Targets.cmake由前面EXPORT参数生成的文件,用于find_package查找DESTINATION ${TARGET_INSTALL_LIBDIR}/cmake/${TARGET_NAME} #DESTINATION 需要安装到的路径
)include(CMakePackageConfigHelpers)
write_basic_package_version_file( #生成库版本相关文件,用于find_package时可以找到库的版本号${TARGET_NAME}ConfigVersion.cmakeVERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}COMPATIBILITY SameMajorVersion
)
configure_package_config_file( #生成库相关文件,用于find_package时可以找到库cmake/PackageConfig.cmake.in ${TARGET_NAME}Config.cmake #cmake/PackageConfig.cmake.in 该文件需要自己编写INSTALL_DESTINATION ${TARGET_INSTALL_LIBDIR}/cmake/${TARGET_NAME} #指定该文件存放的路径
)install(FILES #将上述生成的两个文件安装到指定目录,用于find_package${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}Config.cmake${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}ConfigVersion.cmake DESTINATION${TARGET_INSTALL_LIBDIR}/cmake/${TARGET_NAME}
)
- PackageConfig.cmake.in 文件放在CMakeLists.txt同一级目录下的cmake目录下
XXX
├── cmake
│ └── PackageConfig.cmake.in
├── CMakeLists.txt
- PackageConfig.cmake.in内容如下
@PACKAGE_INIT@ #内置宏set(@PROJECT_NAME@_INCLUDE_DIRS ${PACKAGE_PREFIX_DIR}/include) #配置库头文件路径,对外导出变量@PROJECT_NAME@_INCLUDE_DIRS供外部引用
set(@PROJECT_NAME@_STATIC_LIBRARIES ${PACKAGE_PREFIX_DIR}/lib/lib@TARGET_NAME@.a) #配置库,对外导出变量@PROJECT_NAME@_LIBRARIES供外部引用
set(@PROJECT_NAME@SHARED_LIBRARIES ${PACKAGE_PREFIX_DIR}/lib/lib@TARGET_NAME@.so)include(CMakeFindDependencyMacro)
include(${CMAKE_CURRENT_LIST_DIR}/@TARGET_NAME@Targets.cmake)
check_required_components(@TARGET_NAME@) #检查@TARGET_NAME@
为了能让大家更好的学习鸿蒙(HarmonyOS NEXT)开发技术,这边特意整理了《鸿蒙开发学习手册》(共计890页),希望对大家有所帮助:https://qr21.cn/FV7h05
《鸿蒙开发学习手册》:
如何快速入门:https://qr21.cn/FV7h05
- 基本概念
- 构建第一个ArkTS应用
- ……
开发基础知识:https://qr21.cn/FV7h05
- 应用基础知识
- 配置文件
- 应用数据管理
- 应用安全管理
- 应用隐私保护
- 三方应用调用管控机制
- 资源分类与访问
- 学习ArkTS语言
- ……
基于ArkTS 开发:https://qr21.cn/FV7h05
- Ability开发
- UI开发
- 公共事件与通知
- 窗口管理
- 媒体
- 安全
- 网络与链接
- 电话服务
- 数据管理
- 后台任务(Background Task)管理
- 设备管理
- 设备使用信息统计
- DFX
- 国际化开发
- 折叠屏系列
- ……
鸿蒙开发面试真题(含参考答案):https://qr18.cn/F781PH
鸿蒙开发面试大盘集篇(共计319页):https://qr18.cn/F781PH
1.项目开发必备面试题
2.性能优化方向
3.架构方向
4.鸿蒙开发系统底层方向
5.鸿蒙音视频开发方向
6.鸿蒙车载开发方向
7.鸿蒙南向开发方向
相关文章:
从零开始编写一个cmake构建脚本
简介 本文档介绍cmake构建脚本编写,包含的一些主要元素和命名规范。 cmake构建脚本编写步骤 cmake构建工具版本要明确 # 命令名字要小写,这条语句要求构建工具至少需要版本为3.12或以上 cmake_minimum_required (VERSION 3.12)工程名及库的版本号明确…...
pringboot2集成swagger2出现guava的FluentIterable方法不存在
错误信息 Description: An attempt was made to call a method that does not exist. The attempt was made from the following location: springfox.documentation.spring.web.scanners.ApiListingScanner.scan(ApiListingScanner.java:117) The following method did not ex…...
进程线程的关系
举个例子 滑稽老师吃100只鸡 如何加快滑稽老师吃鸡的效率?? 有一个方案,搞两个房间,两个滑稽老师 一个滑稽吃50只鸡,速度一定会大幅度增加 多进程的方案 创建新的进程 就需要申请更多的资源(房间和…...
一些 VLP 下游任务的相关探索
目录 一、Image-Text Retrieval (ITR , 图像文本检索) 任务目的: 数据集格式 训练流程 evaluation流程 实际使用推测猜想 二、Visual Question Answering (VQA , 视觉问答) 任务目的 数据集格式 训练流程 demo以及评估流…...
【opencv】示例-pca.cpp PCA图像重建演示
// 加载必要的头文件 #include <iostream> // 用于标准输入输出流 #include <fstream> // 用于文件的输入输出 #include <sstream> // 用于字符串的输入输出流操作#include <opencv2/core.hpp> // OpenCV核心功能的头文件 #include "o…...
C语言中的编译和链接
系列文章目录 文章目录 编辑 系列文章目录 文章目录 前言 一、 翻译环境和运行环境 二、 翻译环境 2.1 编译 2.1.1 预处理 2.1.2 编译 2.1.2.1 词法分析 : 2.1.2.2 语法分析 2.1.2.3 语义分析 2.1.3 汇编 2.2 链接 三、运行环境 前言 在我们平常的写代码时,我们很…...
如何将三方库集成到hap包中——通过IDE集成cmak构建方式的C/C++三方库
简介 cmake构建方式是开源三方库的主流构建方式。DevEco Studio目前以支持cmake的构建方式。本文将通过在IDE上适配cJSON三方库为例讲来解如何在IDE上集成cmake构建方式得三方库。 创建工程 在开发进行三方库适配以及napi接口开发前,我们需要创建一个三方库对应的…...
Towards Street-Level Client-Independent IP Geolocation(2011年)(第二部分)
被引次数:306 Wang Y, Burgener D, Flores M, et al. Towards {Street-Level}{Client-Independent}{IP} Geolocation[C]//8th USENIX Symposium on Networked Systems Design and Implementation (NSDI 11). 2011. 接着Towards Street-Level Client-Independent IP Geolocati…...
软件测试过程和测试生命周期
众所周知,软件生命周期包括,需求阶段、设计阶段、设计构建阶段、测试周期阶段、最后测试、实施阶段、最后运维和维护验收。每个阶段都需要在软件开发的生命周期中从前一阶段交付。需求转化为设计,设计转化为开发和开发成测试,经过…...
python-study-day1
ps:前言 可做毕设,html,web,app,小程序,bug修改,可加急 作者自述 作为一名前端开发工程师,这个大环境不好的情况下,我试过我前端接单子但是没有后端,…...
【Apache2】彻底删除 Apache2 服务器
要彻底删除 Apache2 服务器,需要卸载 Apache2 软件包并删除其配置文件和数据文件。在 Ubuntu 上,可以按照以下步骤来完成: 停止 Apache2 服务: sudo systemctl stop apache2卸载 Apache2 软件包: sudo apt-get purge a…...
C#:成绩等级转换
任务描述 本关任务:给出一百分制成绩,要求输出成绩等级‘A’、‘B’、‘C’、‘D’、‘E’。 90分以上为A 80-89分为B 70-79分为C 60-69分为D 60分以下为E,如果输入数据不在0~100范围内,请输出一行:“Score is error!”…...
每日OJ题_01背包③_力扣494. 目标和(dp+滚动数组优化)
目录 力扣494. 目标和 问题解析 解析代码 滚动数组优化代码 力扣494. 目标和 494. 目标和 难度 中等 给你一个非负整数数组 nums 和一个整数 target 。 向数组中的每个整数前添加 或 - ,然后串联起所有整数,可以构造一个 表达式 : …...
vue3+element plus图片预览点击按钮直接显示图片的预览形式
1 需求 直接上需求: 我想要直接点击下面这个“预览”按钮,然后呈现出预览图片的形式 ok,需求知道了,下面让我们来看看如何实现吧 ~ 2 实现 template部分 <el-buttontype"primary"size"small"click&qu…...
GAMS104 现代游戏引擎 2
渲染的难点可以分为一下三部分:如何计算入射光线、如何考虑材质以及如何实现全局光照。 渲染的难点之一在于阴影,或者说是光的可见性。如何做出合适的阴影效果远比想象中要难得多,在实践中往往需要通过大量的技巧才能实现符合人认知的阴影效…...
spring boot学习第十七篇:OAuth2概述及使用GitHub登录第三方网站
0. 导言 我们在浏览器上可以访问成百上千个网站,使用每个网站的服务一般都要先注册账号,那么我们为了更好地记忆,一般都会在多个网站使用相同的账号和密码进行注册。那么问题就来了,如果在你注册的网站中有某些个网站的系统设计不…...
基于springboot的电影评论网站系统源码数据库
基于springboot的电影评论网站系统源码数据库 随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施在技术上已逐步成熟。本文介绍了电影评论网站的开发全过程。通过分析电影评论网站管理的不足,创建了一个计算机管理电影评论网站的方案。文…...
javaScript手写专题——实现instanceof/call/apply/bind/new的过程/继承方式
目录 原型链相关 手写instanceof 实现一个_instance方法,判断对象obj是否是target的实例 测试 手写new的过程 实现一个myNew方法,接收一个构造函数以及构造函数的参数,返回构造函数创建的实例对象 测试myNew方法 手写类的继承 ES6&…...
C++11 新特性:tuple 元组
std::tuple是 C11 中引入的一个非常强大的类型,它允许将多个类型不同的值,组合成单一对象。 std::tuple非常适合用于那些需要返回多个值的场景,而且它的灵活性和通用性使得其成为现代 C 编程中不可或缺的一部分。下面,我们将探讨…...
最齐全,最简单的免费SSL证书获取方法——实现HTTPS访问
一:阿里云 优势:大平台,在站长中知名度最高,提供20张免费单域名SSL证书 缺点:数量有限,并且只有单域名证书,通配符以及多域名没有免费版本。并且提供的单域名证书只有三个月的期限。 二&#…...
c语言->贪吃蛇实战技巧结合EasyX简单实现页面管理(简单实现)
✅作者简介:大家好,我是橘橙黄又青,一个想要与大家共同进步的男人😉😉 🍎个人主页:再无B~U~G-CSDN博客 1. 游戏背景 贪吃蛇是久负盛名的游戏,它也和俄罗斯⽅…...
C语言-详解内存函数
文章目录 1.memcpy使用和模拟实现1.1 memcpy函数的使用规则1.2 memcpy函数的使用1.2 模拟实现memcpy函数 2.memmove 函数的使用和模拟实现2.1 memmove 函数使用规则2.2 memmove函数的使用2.3 模拟实现memmove函数2.3.1 从后往前移2.3.2 从前往后移 2.4 算法实现2.4.1 从前往后移…...
【核心完整复现】基于目标级联法的微网群多主体分布式优化调度
1 主要内容 之前发布了华电学报的复现程序《基于目标级联法的微网群多主体分布式优化调度》,具体链接为【防骗版】基于目标级联法的微网群多主体分布式优化调度,虽然对模型及结果进行了复现,但是部分模型细节和参数并没有完全实现࿰…...
Mac下安装NVM,NVM安装Node(附带NPM)
1、理解NVM、node、NPM 什么是NVM? NVM: Node.js Version Manager,用来管理 node 的版本。 什么是 Node.js? Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。 Node.js使用了一个事件驱动、非阻塞式I/O的模型( Node.js的特性&…...
java之变量的作用域
在java中,变量需要像其他编程语言中先定义,再使用。但并不是定义好就能用。需要对变量定义一个作用范围才能使用,这个作用范围称为作用域。 在java程序中,变量会定义在一个花括号内,花括号内的区域就是作用域。 比如…...
CentOS 7软件安装全攻略:YUM命令详解与实战
在CentOS 7中,软件安装主要依赖于其强大的包管理器——YUM(Yellowdog Updater Modified)。YUM可以自动解决软件包之间的依赖关系,使得软件的安装、更新和卸载变得简单而高效。本文将详细介绍CentOS 7中软件安装的相关命令、选项和…...
达梦关键字(如:XML,EXCHANGE,DOMAIN,link等)配置忽略
背景:在使用达梦数据库时,查询SQL中涉及XML,EXCHANGE,DOMAIN,link字段,在达梦中是关键字,SQL报关键词不能使用的错误。 解决办法: 配置达梦安装文件E:\MyJava\dmdbms\data\DAMENG\dm.ini 忽略这些关键词,…...
2024/4/11 直流电机调速/PWM
一、直流电机简介和PWM原理 直流电机是一种将电能转换为机械能的装置。一般的直流电机有两个电极,当电极正接时,电机正转,当电极反接时,电机反转 直流电机主要由永磁体(定子)、线圈(转子&…...
贝乐虎儿歌v6.8.0解锁高级版亲子学习儿歌
软件介绍 贝乐虎儿歌免费版app,出自乐擎网络的创意工坊,专为孩子们雕琢了一系列富含创意的动画儿歌内容。这款app通过贝乐虎兄弟的可爱形象,让孩子们在愉快的观看中接触到各种儿歌和故事。不仅如此,app还巧妙地将古诗、英语等学习…...
计算机网络技术-RIP、0SPF和BGP协议的工作原理和应用
目录 RIP (Routing Information Protocolv)路由信息协议OSPF(Open Shortest Path First) 开放式最短路径优先BGP( Border Gateway Protocol)边界网关协议 RIP (Routing Information Protocolv)路由信息协议 RIP协议 是 TCP/IP环境中开发的第一个路由选择…...
做网站商城需要多少钱/怎么做网站排名
MySQL 有许多图形化的管理工具,我们在此介绍二个官方的工具「MySQL Administrator」及「MySQL Query Browser」。MySQL Administrator 是用来管理 MySQL Server 用的,您可以查看目前系统状态、新增使用者等。而 MySQL Query Browser 可以用来查看数据库内…...
个人电子邮件注册网站申请/市场监督管理局电话
下载安装 官网下载安装:https://www.sublimetext.com/Package Control:https://packagecontrol.io/官方文档:https://www.sublimetext.com/docs/index.html非官方文档(有很多对官方文档的说明):https://do…...
滁州做网站优化/百度投放广告收费标准
在本文中,我们会研究一些用于数据科学任务的 Python 库,而不是常见的比如 panda、scikit-learn 和 matplotlib 等的库。尽管像 panda 和 scikit-learn 这样的库,是在机器学习任务中经常出现的,但是了解这个领域中的其它 Python 产…...
老榕树建站软件/百度指数搜索榜
以一个马戏团要在某小镇表演而作的市场活动为例: 如果你在街上作一个牌子,写上“xxx马戏团将于x月x日在本镇上演大戏”,这就是在做“广告”。 如果你在马戏团里找一头大象,把这个牌子放在大象的背上,在大街上来回走动&…...
wordpress插件的作用/十大中文网站排名
为了画个图,被numpy这个模块的安装真的折腾疯了!!!一直装不上,花了几个小时,看了网上的很多教程、方法发现总结得不是很全,这里总结一下,防止大家再出现这个问题没有解决方法。Pytho…...
做网站运营好还是SEO好/网站登录入口
怎么设置legacy启动?现在新型电脑都是采用uefi gpt启动模式,以适应win8、win10这些新型操作系统,不过win7之前的系统大多不支持uefi,而是采用legacy启动模式,硬盘分区表是MBR,而不是GPT,如果要在…...