从零开始编写一个cmake构建脚本

news2024/11/23 8:50:59

简介

本文档介绍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种

  • 引用其他三方库的源码

    1. 源码有cmake构建脚本,直接通过add_subdirectory()引用该三方库
     add_subdirectory(xxx)  # xxx是需要引入的三方库源码文件夹名字
  1. 源码非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)

    1. 通过target_link_libraries方法引入,此方法需要指定so的路径:
    target_link_libraries(${TARGET_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/XXX) # 引用当前源码路径下的xxx库
  1. 使用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_package
        PUBLIC_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.cmake
    VERSION ${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

  1. 基本概念
  2. 构建第一个ArkTS应用
  3. ……

开发基础知识:https://qr21.cn/FV7h05

  1. 应用基础知识
  2. 配置文件
  3. 应用数据管理
  4. 应用安全管理
  5. 应用隐私保护
  6. 三方应用调用管控机制
  7. 资源分类与访问
  8. 学习ArkTS语言
  9. ……

基于ArkTS 开发:https://qr21.cn/FV7h05

  1. Ability开发
  2. UI开发
  3. 公共事件与通知
  4. 窗口管理
  5. 媒体
  6. 安全
  7. 网络与链接
  8. 电话服务
  9. 数据管理
  10. 后台任务(Background Task)管理
  11. 设备管理
  12. 设备使用信息统计
  13. DFX
  14. 国际化开发
  15. 折叠屏系列
  16. ……

鸿蒙开发面试真题(含参考答案):https://qr18.cn/F781PH

鸿蒙开发面试大盘集篇(共计319页):https://qr18.cn/F781PH

1.项目开发必备面试题
2.性能优化方向
3.架构方向
4.鸿蒙开发系统底层方向
5.鸿蒙音视频开发方向
6.鸿蒙车载开发方向
7.鸿蒙南向开发方向

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

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

相关文章

spring boot学习第十七篇:OAuth2概述及使用GitHub登录第三方网站

0. 导言 我们在浏览器上可以访问成百上千个网站,使用每个网站的服务一般都要先注册账号,那么我们为了更好地记忆,一般都会在多个网站使用相同的账号和密码进行注册。那么问题就来了,如果在你注册的网站中有某些个网站的系统设计不…

C语言-----结构体详解

前面已经向大家介绍过一点结构体的知识了,这次我们再来深度了解一下结构体。结构体是能够方便表示一个物体具有多种属性的一种结构。物体的属性可以转换为结构体中的变量。 1.结构体类型的声明 1.1 结构体的声明 struct tag {member-list;//结构体成员变量 }vari…

VLC-Qt实现简单的视频播放器

VLC-Qt是一个结合了Qt应用程序和libVLC的免费开源库。它提供了用于媒体播放的核心类,以及用于快速开发媒体播放器的GUI类。由于集成了整个libVLC,VLC-Qt具备了libVLC的所有特性, 例如:libVLC实例和播放器、单个文件和列表播放、音…

海山数据库(He3DB)原理剖析:浅析Doris跨源分析能力

Doris湖仓分析背景: Doris多数据源功能演进 Doris的生态近年来围绕湖仓分析做了较多工作,Doris一直在积极拓宽大数据生态的OLAP分析市场,Doris2.0之后为了满足湖仓分析场景,围绕multi-catalog、数据缓存、容错、pipeline资源管理…

LibRadtran使用教程

LibRadtran使用教程 1.简介2.基本语法规则3.例子3.1 例子13.2 例子2 1.简介 关于LibRadtran的介绍以及安装可以参考另一篇博文&#xff1a;Windows系统LibRadtran安装。这里将针对LibRadtran的基础使用&#xff0c;以及基本语法进行介绍。 2.基本语法规则 uvspec < input…

【前端】layui table表格勾选事件,以及常见模块

欢迎来到《小5讲堂》&#xff0c;大家好&#xff0c;我是全栈小5。 这是《前端》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解&#xff0c; 温馨提示&#xff1a;博主能力有限&#xff0c;理解水平有限&#xff0c;若有不对之处望指正&#xff01; 目录 表格勾选事…

itop4412编译内核时garbage following instruction -- `dmb ish‘ 解决方案

王德法 没人指导的学习路上磕磕绊绊太耗费时间了 今天编译4412开发板源码时报 garbage following instruction – dmb ish’ 以下是解决方案&#xff1a; 1.更新编译器 sudo apt-get install gcc-arm-linux-gnueabi 更新后修改Makefile 中编译器路径如下图 2.你以为更新完就可…

OpenHarmony实例应用:【常用组件和容器低代码】

介绍 本篇Codelab是基于ArkTS语言的低代码开发方式实现的一个简单实例。具体实现功能如下&#xff1a; 创建一个低代码工程。通过拖拽的方式实现任务列表和任务信息界面的界面布局。在UI编辑界面实现数据动态渲染和事件的绑定。 最终实现效果如下&#xff1a; 相关概念 低代…

【Blockchain】连接智能合约与现实世界的桥梁Chainlink

去中心化预言机试图实现依赖因果关系而不是个人关系的去信任和确定性结果。它以与区块链网络相同的方式实现这些结果&#xff0c;即在许多网络参与者之间分配信任。通过利用许多不同的数据源并实施不受单个实体控制的预言机系统&#xff0c;去中心化的预言机网络有可能为智能合…

【Python习题】用turtle库直角三角形,底边长150,斜边长300,底角60度,线条粗6像素,线条颜色为蓝色,填充颜色为红色

完整题干&#xff1a; &#xff08;1&#xff09;从Python官网下载Python3.7安装包&#xff0c;安装并熟悉 Python IDLE编程环境。 &#xff08;2&#xff09;在 Python IDLE Shell 窗口中编写程序计算圆的周长。 &#xff08;3&#xff09;编写程序&#xff0c;绘制如图1.10…

Java基础第十一课——类与对象(2)

由于类与对象这一部分的知识点很多&#xff0c;而且操作方法也有很多&#xff0c;所以这次将继续深入讨论一下关于类与对象中方法传参、方法重载、构造方法以及this关键字使用方面的知识。 一、方法传参 1.return关键字 return关键字作用 作用场景&#xff1a;方法内 作用…

C语言 函数——函数封装与程序的健壮性

目录 函数封装&#xff08;Encapsulation&#xff09; 如何增强程序的健壮性&#xff1f; 如何保证不会传入负数实参&#xff1f; 函数设计的基本原则 函数封装&#xff08;Encapsulation&#xff09; 外界对函数的影响——仅限于入口参数 函数对外界的影响——仅限于一个…

降额的秘密——不要挑战datasheet!

原文来自微信公众号&#xff1a;工程师看海&#xff0c;与我联系&#xff1a;chunhou0820 看海原创视频教程&#xff1a;《运放秘籍》 大家好&#xff0c;我是工程师看海。 什么是降额设计&#xff1f;我们为什么要降额&#xff1f; 额指的是额定工作状态&#xff0c;降额就是…

数据结构——单链表(C语言版)

文章目录 一、链表的概念及结构二、单链表的实现SList.h链表的打印申请新的结点链表的尾插链表的头插链表的尾删链表的头删链表的查找在指定位置之前插入数据在指定位置之后插入数据删除pos结点删除pos之后的结点销毁链表 三、完整源代码SList.hSList.ctest.c 一、链表的概念及…

基于YOLOv5s的电动车入梯识别系统(数据集+权重+登录界面+GUI界面+mysql)

本文目录 1.UI界面 2.注册登录 3.算法准确率 4.数据集 1.UI界面 本人训练的yolov5s模型&#xff0c;准确率在98.6%左右&#xff0c;可准确完成电梯内检测电动车任务&#xff0c;并搭配了GUI检测界面&#xff0c;支持权重选择、图片检测、视频检测、摄像头检测、识别结果拍照…

喜报!成都爱尔眼科医院再次获得成都市医学科技三等奖!

2024年4月10日&#xff0c;“2024年全市医疗管理和科教服务工作暨培训会”在成都市血液中心召开。会议为期一天&#xff0c;落实2024年全国、全省医政管理工作会和全省、全市卫生健康工作会等相关会议精神&#xff0c;总结2023年全市医疗管理和科教服务工作情况&#xff0c;部署…

go语言基础 -- 反射

反射的基本介绍 反射可以在运行时动态获取变量的信息&#xff0c;如变量的类型&#xff08;type&#xff09;&#xff0c;类别(kind)。如果是结构体变量&#xff0c;还可以获取到变量的字段、方法等结构体本身信息&#xff1b;通过反射&#xff0c;可以修改变量的值或调用关联…

【蓝桥杯】第十五届填空题a.握手问题

题解&#xff1a; 根据问题描述&#xff0c;总共有 50 人参加会议&#xff0c;每个人除了与自己以外的其他所有人握手一次。但有 7 个人彼此之间没有进行握手&#xff0c;而与其他所有人都进行了握手。 首先&#xff0c;计算所有人进行握手的总次数&#xff1a; 总人数为 50 …

LabVIEW电信号傅里叶分解合成实验

LabVIEW电信号傅里叶分解合成实验 电信号的分析与处理在科研和工业领域中起着越来越重要的作用。系统以LabVIEW软件为基础&#xff0c;开发了一个集电信号的傅里叶分解、合成、频率响应及频谱分析功能于一体的虚拟仿真实验系统。系统不仅能够模拟实际电路实验箱的全部功能&…

对给定向量旋转

对给定向量旋转 顺时针&#xff1a; 逆时针&#xff1a; 源码&#xff1a; QPointF rotateVector(const QPointF& dir, double angle, bool flag){double rad (angle * M_PI) / 180;QPointF res;if (flag){float x static_cast<float>(dir.x() * std::cos(rad) …