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

三、cmake语法-提高篇

目录

上一章节

一、前言

二、库文件的制作

1、静态库

2、动态库

3、指定库文件输出路径

三、库文件的使用

1、静态库的使用

1.1、指定库文件路径

2、动态库的使用

四、日志打印

1、消息等级:

五、变量操作

1、字符串的拼接

(1)set命令

(2)list 命令

2、字符列表中剔除字符串

3、List 命令介绍

(1)LENGTH 获取字符串长度

(2)GET 列表通过索引获取字符串

(3)JOIN指定连接符将列表中字符串连接起来

(4)FIND在列表中查找字符串,并返回索引

(5)INSERT在列表指定位置后插入若干元素

(6)PREPEND在列表最前面插入元素

(7)POP_BACK移除列表最后一个元素

(8)POP_FRONT移除列表第一个元素

(9)REMOVE_AT移除列表指定位置元素

(10)ROMOVE_DUPLICATES移除重复元素

(11)REVERSE列表翻转

(12)SORT列表排序

六、自定义宏

1、通过gcc, 命令编译指定宏

2、通过CMakeLists.txt中指定

七、总结


上一章节

https://blog.csdn.net/weixin_36323170/article/details/151336498?spm=1001.2014.3001.5501https://blog.csdn.net/weixin_36323170/article/details/151336498?spm=1001.2014.3001.5501

一、前言

开启本文之前先做个知识点的梳理,这里主要介绍库文件的制作与使用、日志打印、变量操作、宏定义等

二、库文件的制作

前面介绍了主要是生成可执行文件,但是我们在实际工作中会遇到,给别人提供第三方库的场景,这里就需要将开发的源代码编译成库文件,这里介绍在cmake下如何制作库文件

1、静态库

制作静态库命令如下:

add_library(库名称 STATIC 源文件1 [源文件2] ...) 

编译生成的库文件常见名称构成如下:

linux下:lib+库名称+.a

windows下:lib+库名称+.lib,这里必须是window自带的msvc原生工具链,cl.exe编译生成的;

如果使用mingw在windows系统下编译生成的依然是.a结尾的库,这里使用仍然要在相同工具链下引用才可以,否则会出现二进制不兼容。

例如:

cmake_minimum_required(VERSION 3.10)# 项目名称和支持的语言(显式指定C语言)
project(CMTEST LANGUAGES C)# 设置C标准版本(根据需要调整,例如C99、C11)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/lib) # 指定库文件输出目录
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src SRC_LST)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)add_library(calc STATIC  ${SRC_LST})  

生成静态库:

2、动态库

动态库制作命令

add_library(库名称 SHARED 源文件1 [源文件2] ...) 

Linux下: lib+库名称+.so

Windows下:lib+库文件+.dll

例如:

cmake_minimum_required(VERSION 3.10)# 项目名称和支持的语言(显式指定C语言)
project(CMTEST LANGUAGES C)# 设置C标准版本(根据需要调整,例如C99、C11)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/lib) # 指定库文件输出目录
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src SRC_LST) # 将源文件指定给变量SRC_LST
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)add_library(calc SHARED  ${SRC_LST}) # 制作动态库并指定名称为calc

生成库文件:

3、指定库文件输出路径

LIBRARY_OUTPUT_PATH:该关键字用于指定库文件的输出路径;

三、库文件的使用

库文件使用必须有两个部分,首先是头文件(获取到库文件中所包含的函数声明,以及类对象等信息), 再一个就是库文件。

例如下目录结构:

1、静态库的使用

链接静态库命令如下:

link_libraries(<static lib> [<static lib>...])

这里指定链接库,此处参数可做如下的要求:

参数1:指定链接库的名字,(1)、可以是全名例如 libcalc.a; (2)、也可以是掐头去尾,留下calc

参数2:缺省,可以在一条命令中指定多个静态库

如果该库是自定义的,或者第三方提供的,这里不是系统库,有可能存在找不到的情况;这里有两个解决办法

(1)、使用环境变量,将该库的存放文件夹路径放到环境路径下;

(2)、自己在CMakeLists.txt中添加该库存放路径,最好是相对当前项目的相对路径,这样保证在与他人合作时。路径统一,推荐此种方法;

1.1、指定库文件路径

link_directories(<lib path>) # 可以一次性指定多个静态库/动态库的路径

例如下CMakeLists.txt

cmake_minimum_required(VERSION 3.10)# 项目名称和支持的语言(显式指定C语言)
project(CMTEST LANGUAGES C)# 设置C标准版本(根据需要调整,例如C99、C11)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
file(GLOB SRC ${CMAKE_CURRENT_SOURCE_DIR}/*.c) # 获取当前目录下的所有C源文件
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)link_directories(${CMAKE_CURRENT_SOURCE_DIR}/lib) # 设置静态库目录
link_libraries(calc)# 链接静态库add_executable(testapp ${SRC}) 

编译-》链接 生成可执行文件

静态库编译后会直接编译到可执行文件中,因此在使用可执行文件时,不依赖静态库;

2、动态库的使用

在正常软件开发过程中,需要多人协作,有时候会将各个功能模块分开,这里各自维护各自的动态库,再最终软件运行时,将这些动态库串联起来,这里就要提到动态库的使用。

target_link_libraries: 链接动态库/静态库,用于指定编译一个源文件/库文件/可执行文件时需要链接的动态库

target_link_libraries(<target> <PRIVATE|PUBLIC|INTERFACE> <item>... [<PRIVATE|PUBLIC|INTERFACE> <item>...]...)

(1)、target: 指定要加载库文件的名字

这里可以是一个源文件/动态库/静态库/可执行文件。

(2)、PRIVATE|PUBLIC|INTERFACE:动态库访问权限,默认PUBLIC

若动态库之间没有相互依赖关联,则默认用PUBLIC

PUBLIC:在public后面的库会被Link到前面的target中,并且里面的符号也会被导出,提供给第三方使用,可以理解为当前目标 “使用” 了该库,并且把该库的接口等资源“暴露” 给了依赖自己的目标(即其他目标依赖当前目标时,相当于间接依赖了这个库) ;

PRIVATE:在private后面的库仅被link到前面的target中,并且终结掉,第三方不能感知你调了啥库,对于第三方使用当前目标库依赖时,屏蔽了目标库依赖的库;

INTERFACE:在interface后面引入的库不会被链接到前面的target中,只会导出符号。可以理解为当前目标本身不用这个库,但要求所有依赖自己的目标必须依赖这个库(相当于 “转发” 依赖);

(3)、动态库的链接具有传递性,如果动态库 A 链接了动态库B、C,动态库D链接了动态库A,此时动态库D相当于也链接了动态库B、C,并可以使用动态库B、C中定义的方法。

target_link_libraries(A B C)
target_link_libraries(D A)
# 这里D相当于链接了BC

(4)、编译可执行文件链接动态库时,链接要写在可执行文件后面,指定动态库时需要掐头去尾,去除开头的lib跟结尾的.dll/.so

cmake_minimum_required(VERSION 3.10)# 项目名称和支持的语言(显式指定C语言)
project(CMTEST LANGUAGES C)# 设置C标准版本(根据需要调整,例如C99、C11)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
file(GLOB SRC ${CMAKE_CURRENT_SOURCE_DIR}/*.c) # 获取当前目录下的所有C源文件
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)link_directories(${CMAKE_CURRENT_SOURCE_DIR}/bin) # 设置动态库目录add_executable(testapp ${SRC}) target_link_libraries(testapp PUBLIC calc) # 链接动态库

编译生成的可执行文件,运行时需要将动态库放置到同级路径下,否则会报如下错误:

(5)、动态库跟静态库差异,动态库不会编译到目标文件中,但是静态库会直接编译进去,因此最终生成目标文件,静态库编译方式生成的文件较大,动态库链接方式生成的较小;

四、日志打印

命令:message

message([STATUS|WARNING|AUTHOR_WARNING|FATAL_ERROR|SEND_ERROR] "message to display" ...)

1、消息等级:

(无) :重要消息

STATUS :非重要消息

WARNING:CMake 警告, 会继续执行

AUTHOR_WARNING:CMake 警告 (dev), 会继续执行

SEND_ERROR:CMake 错误, 继续执行,但是会跳过生成的步骤

FATAL_ERROR:CMake 错误, 终止所有处理过程

# 输出一般日志信息
message(STATUS "source path: ${PROJECT_SOURCE_DIR}")
# 输出警告信息
message(WARNING "source path: ${PROJECT_SOURCE_DIR}")
# 输出错误信息
message(FATAL_ERROR "source path: ${PROJECT_SOURCE_DIR}")

五、变量操作

1、字符串的拼接

(1)set命令

set(变量名 ${参数1}  ${参数2} ...) # 将后面的参数1/2拼接成一个字符串,赋值给变量

这里如果原来变量有值会被覆盖, 可以是常量字符串,也可以是变量字符串

set(temp hello world)
set(temp1 ${temp} gg)
message(${temp})
message(${temp1})

(2)list 命令

list(APPEND <list> [<element> ... ])

指定字符串list, 采用追加发方式,将后续成员字符追加到list后面;

list在管理字符串时,采用链表的方式存储,字符串之间用‘,’分隔,但是在message命令打印时,整体是一个字符串

2、字符列表中剔除字符串

使用List 命令

list(REMOVE_ITEM <list> <value> [<value> ...])

在字符串list,中删除后续的value值的字符串,可以是一个也可以是多个;

3、List 命令介绍

(1)LENGTH 获取字符串长度

list(LENGTH <list> <output variable>) # list 当前操作列表, <output variable>创建新的变量,用于存储长度

(2)GET 列表通过索引获取字符串

list(GET <list> <element index> [<element index> ...] <output variable>)

 <list>:当前操作列表

 <element index>:列表元素的索引, 索引0开始编号,0表示第一元素;负数表示从最后一个元素开始,-1表示最后一个元素,以此类推;索引不管正负不能超过实际长度,否则运行报错;

<output variable>:新创建的变量,存储指定索引元素的返回结果,也是一个列表

(3)JOIN指定连接符将列表中字符串连接起来

list (JOIN <list> <glue> <output variable>)

<list>:当前操作列表

<glue>:指定连接符

<output variable>:创建新变量,存储返回的字符串

(4)FIND在列表中查找字符串,并返回索引

list(FIND <list> <value> <output variable>)

<value>:列表中搜索的字符串

<output variable>:新创建的变量,若搜索到字符串,则返回该字符串的索引,否则返回-1

(5)INSERT在列表指定位置后插入若干元素

list(INSERT <list> <element_index> <element> [<element> ...])

(6)PREPEND在列表最前面插入元素

list (PREPEND <list> [<element> ...])

(7)POP_BACK移除列表最后一个元素

list (POP_BACK <list> [<out-var>...])

(8)POP_FRONT移除列表第一个元素

list (POP_FRONT <list> [<out-var>...])

(9)REMOVE_AT移除列表指定位置元素

list (REMOVE_AT <list> <index> [<index> ...])

(10)ROMOVE_DUPLICATES移除重复元素

list (REMOVE_DUPLICATES <list>)

(11)REVERSE列表翻转

list(REVERSE <list>)

(12)SORT列表排序

list (SORT <list> [COMPARE <compare>] [CASE <case>] [ORDER <order>])

COMPARE:指定排序方法。有如下几种值可选:

STRING:按照字母顺序进行排序,为默认的排序方法

FILE_BASENAME:如果是一系列路径名,会使用basename进行排序

NATURAL:使用自然数顺序排序

CASE:指明是否大小写敏感。有如下几种值可选:

SENSITIVE: 按照大小写敏感的方式进行排序,为默认值

INSENSITIVE:按照大小写不敏感方式进行排序

ORDER:指明排序的顺序。有如下几种值可选:

ASCENDING:按照升序排列,为默认值

DESCENDING:按照降序排列

六、自定义宏

我们在代码运行时添加一些宏,从而控制代码内部的执行逻辑,可以灵活控制编译过程中的执行逻辑,是项目管理和功能开关的常用手段。

例如:

#include <stdio.h>
#define NUMBER  3int main()
{int a = 10;
#ifdef DEBUG  // 这里对该宏进行判断,如果被定义了,这执行这部分代码,没定义,相当于此处为注释掉的代码printf("这里是编译调试...\n");
#endiffor(int i=0; i<NUMBER; ++i){printf("hello, word!!!\n");}return 0;
}

针对这个宏,可以采用如下两个方式定义:

1、通过gcc, 命令编译指定宏

gcc hello.c -DDEBUG -o app

2、通过CMakeLists.txt中指定

add_definitions

add_definitions(-D宏名称)

七、总结

        至此,关于 CMake 语法提高篇的核心内容已梳理完毕。从库文件的构建到实际应用,再到变量、宏定义等高级特性的灵活运用,我们能清晰感受到 CMake 作为跨平台构建工具的强大与便捷 —— 它不仅能通过统一的语法解决不同系统下库文件格式差异的问题,还能借助路径管理、条件判断等功能,让复杂项目的构建流程更具逻辑性和可维护性。

http://www.dtcms.com/a/541035.html

相关文章:

  • 仓颉编程(20)泛型
  • Go语言2D游戏开发入门004:零基础打造射击游戏《太空大战》3
  • 学习FreeRTOS(FreeRTOS移植到STM32F103C8T6)
  • json缩放 json 缩放
  • maxkb部署,版本升级步骤与注意事项(超详细图文)
  • 测试开发话题02---概念篇
  • 网站建设推广优化排名全国工商核名查询系统官网
  • ASP Content Linking
  • 【研究生随笔】Pytorch中的卷积神经网络(1)
  • Android运行项目报错集合
  • 为什么电脑会蓝屏?怎么快速解决电脑蓝屏问题
  • js建设网站html5网站开发价格
  • ESP32学习笔记(基于IDF):OneNET物模型数据交互(控制小灯)
  • JavaScript逆向与爬虫实战——基础篇(css反爬之动态字体实现原理及绕过)
  • 浏览器在请求 js/css 静态文件时,服务器返回了 500 内部错误 500 Internal Server Error
  • CSS 实现酷炫的不规则圆角与斜角边框效果(四种方法详解)
  • 在线网站地图生成器自建购物网站多少钱
  • 网站开发的整个流程一家只做卫生巾的网站
  • xv6-riscv开发调试环境搭建(vscode+ubuntu)
  • 架构兜底五大手段:构建韧性系统的全面防御体系
  • 阿里巴巴有几个网站是做外贸的wordpress 禅意主题
  • 在 `PaddleOCR` 中配置自定义模型(如自己训练的检测/识别模型)
  • 云谷系统网站开发网站备案要收费吗
  • 前端页面初始化加载速度优化方案
  • 【数据库】金仓数据库构建集团化医院全栈信创“全链路解决方案”
  • MATLAB基于自适应动态特征加权的K-means算法
  • 我的Dify OCR 识别发票准确率测试工具
  • 免费域名申请网站大全封面型网站首页怎么做
  • 专业的网站建设化妆品备案
  • 详解使用CodeBuddy解决高难度项目问题