从零开始编写一个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种

  • 引用其他三方库的源码

    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.鸿蒙南向开发方向

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

阿里面试总结 一

写了这些还是不够完整,阿里 字节 卷进去加班!奥利给 ThreadLocal 线程变量存放在当前线程变量中,线程上下文中,set将变量添加到threadLocals变量中 Thread类中定义了两个ThreadLocalMap类型变量threadLocals、inheritableThrea…

深度学习的模型有几类,能干嘛用?

1、基础模型 (1)卷积神经网络 **卷积:**卷积的本质是通过矩阵运算9的方式将输入数据进行空间上的滤波,有效地提取数据中的局 部特征,从而实现特征数据更高程度的抽象表示。 **池化:**可以理解成“压缩”…

火绒安全软件:程序员的网络守护天使

目录 前言 系统防护 网络防护 隐私保护 高级设置 软件安全 响应速度 持续更新 总结 前言 在这个充满机遇与挑战的数字时代,程序员们如同探险家,不断探索着代码的新大陆。然而,网络世界也充斥着各种未知的风险和威胁。火绒安全软件&a…

浏览器工作原理与实践--渲染流水线:CSS如何影响首次加载时的白屏时间

在上一篇文章中我们详细介绍了DOM的生成过程,并结合具体例子分析了JavaScript是如何阻塞DOM生成的。那本文我们就继续深入聊聊渲染流水线中的CSS。因为CSS是页面中非常重要的资源,它决定了页面最终显示出来的效果,并影响着用户对整个网站的第…

初识 QT

初始QT 什么是QTQT发展史QT支持的平台QT的优点QT的应用场景搭建QT开发环境QT的开发工具概述QT下载安装 使用QT创建项目QT 实现Hello World程序使用按钮控件来实现使用标签控件来实现 项目文件解析widget.hmain.cppwidget.cppwidget.ui.pro文件 对象树QT 窗口坐标体系 什么是QT …

STM32H7的MPU学习和应用示例

STM32H7的MPU学习记录 什么是MPU?MPU的三种内存类型内存映射MPU保护区域以及优先级 MPU的寄存器XN位AP位TEX、C、B、S位SRD 位SIZE 位CTRL 寄存器的各个位 示例总结 什么是MPU? MPU(Memory Protection Unit,内存保护单元&#xf…

LeetCode最长有效括号问题解

给定一个仅包含字符的字符串(’ 和 ‘)’,返回最长有效的长度(出色地-形成) 括号子弦。 示例1: 输入:s “(()” 输出:2 说明:最长的有效括号子字符串是 “()” 。 示例2: 输入:s “)()())…

5分钟手把手教你 Guitar Pro v8.1.1 Build 17 中文完整激活版(附教程) 64位

吉他爱好者必备神器:Guitar Pro v8.1.1 Build 17深度解析 随着数字音乐制作和学习的日益普及,越来越多的吉他爱好者开始寻找能够帮助他们提升技能、创作音乐的专业工具。在众多吉他制作软件中,Guitar Pro因其强大的功能和易用的界面备受推崇…

Linux内核中KASLR功能是什么?有什么作用?怎么破除?以及如何实操?(地址空间、layout random、kallsyms)

1. 背景 KASLR是一个什么技术点其实不重要,但重要的是有了KASLR这个功能后,造成内核中某个符号(函数 or 变量)在System.map中的地址和实际不一样了(实际: cat /proc/kallsyms),进一…

JVM性能调优——GC日志分析

文章目录 1、概述2、生成GC日志3、Parallel垃圾收集器日志解析3.1、Minor GC3.2、FULL GC 4、G1垃圾收集器日志解析4.1、Minor GC4.2、并发收集4.3、混合收集4.4、Full GC 5、CMS垃圾收集器日志解析5.1、Minor GC5.2、Major GC5.3、浮动垃圾 6、日志解析工具6.1、GCeasy6.2、GC…

Java代码基础算法练习-自定义函数之求字符串长度-2024.04.13

任务描述: 写一函数,求一个字符串的长度(字符串长度不超过255),然后在主函数中调用该函数 实现求长度操作。 任务要求: 代码示例: package April_2024;import java.util.Scanner;public class …

Spark AQE(Adaptive Query Execution)机制

💐💐扫码关注公众号,回复 spark 关键字下载geekbang 原价 90 元 零基础入门 Spark 学习资料💐💐 AQE 的全称是 Adaptive Query Execution,翻译过来是“自适应查询执行”。它包含了 3 个动态优化特性&#…

Android适配平板屏幕尺寸

一、划分手机和平板 人为判断方法: 大于6英寸的就是平板。小于6英寸的都是手机 平板尺寸: 6英寸、7英寸、10英寸、14英寸… Android系统支持多配置资源文件,我们可以追加新的资源目录到你的Android项目中。命名规范: 资源名字-限制符 l…

Python代码识别minist手写数字【附pdf】

一、概述 对于人类而言,要识别图片中的数字是一件很容易的事情,但是,如何让机器学会理解图片上的数字,这似乎并不容易。那么,能否找出一个函数(模型),通过输入相关的信息&#xff0…

FourCastNet 论文解析

气象基础模型/气象大模型论文速递 论文链接基于arXiv Feb. 22, 2022版本阅读 几乎是第一篇气象大模型的工作,同时也是为数不多的对precipitation进行预测的模型。 文章目录 PerformanceStructureFourier transformToken mixing TrainingPrecipitation Model Ensembl…

科研学习|可视化——Origin绘制相关性系数矩阵

一、Origin软件版本 Origin2021版本 二、插件下载地址 CorrelationPlot.opx资源-CSDN文库 三、插件安装步骤 从上述链接下载插件将插件解压缩(最好是解压缩到orgin的安装目录)用origin打开插件(或者打开origin,将插件拖拽到origin…

Mysql主从复制安装配置

mysql主从复制安装配置 1、基础设置准备 #操作系统: centos6.5 #mysql版本: 5.7 #两台虚拟机: node1:192.168.85.111(主) node2:192.168.85.112(从)2、安装mysql数据库 #详细安装和卸载的步骤…

开源项目one-api的k8s容器化部署(上)-- 制作镜像及部署准备

一、背景 最近需要对开源项目one-api进行k8s容器化部署,主要分以下几个步骤: 制作docker镜像申请mysql和redis数据库docker-compose部署方式k8s部署方式 整个的篇幅比较长,将会分成上下两篇来阐述。 二、制作docker镜像 开源项目one-api…

Vue2 —— 学习(六)

一、Vue 脚手架 (一)介绍 Vue 脚手架是 Vue 官方提供的标准化开发工具 (开发平台) 脚手架版本最新版本 是 4.x 文档可以查看 http://cli.vuejs.org/zh/ 就是vue 官网文档中 的 vue.cli command line interface (…

ChatGPT深度科研应用、数据分析及机器学习、AI绘图与高效论文撰写

2022年11月30日,可能将成为一个改变人类历史的日子——美国人工智能开发机构OpenAI推出了聊天机器人ChatGPT3.5,将人工智能的发展推向了一个新的高度。2023年4月,更强版本的ChatGPT4.0上线,文本、语音、图像等多模态交互方式使其在…