本文主要参考正点原子的应用开发手册,仅作为本人学习笔记使用。

目录

cmake 的使用方法其实还是非常简单的,重点在于编写 CMakeLists.txt,CMakeLists.txt 的语法规则也简单,并没有 Makefile的语法规则那么复杂难以理解!本文我们来学习 CMakeLists.txt 的语法规则。

注释

在 CMakeLists.txt 文件中,使用“#”号进行单行注释,譬如:

#
#这是注释信息
#cmake_minimum_required(VERSION 3.5)
project(HELLO)

大多数脚本语言都是使用“#”号进行注释。

命令(command)

通常在 CMakeLists.txt 文件中,使用最多的是命令,譬如上例中的 cmake_minimum_required、project 都是命令;命令的使用方式有点类似于 C 语言中的函数,因为命令后面需要提供一对括号,并且通常需要我们提供参数,多个参数使用空格分隔而不是逗号“,”,这是与函数不同的地方。命令的语法格式如下所示:

command(参数 1 参数 2 参数 3 ...)

不同的命令所需的参数不同,需要注意的是,参数可以分为必要参数和可选参数(通常称为选项),很多命令都提供了这两类参数,必要参数使用<参数>表示,而可选参数使用[参数]表示,譬如 set 命令:

set(<variable> <value>... [PARENT_SCOPE])

set 命令用于设置变量,第一个参数<variable>和第二个参数<value>是必要参数,在参数列表(…表示参数个数没有限制)的最后可以添加一个可选参数 PARENT_SCOPE(PARENT_SCOPE 选项),既然是可选的,那就不是必须的,根据实际使用情况确定是否需要添加。

在 CMakeLists.txt 中,命令名不区分大小写,可以使用大写字母或小写字母书写命令名,譬如:

project(HELLO) #小写
PROJECT(HELLO) #大写

这俩的效果是相同的,指定的是同一个命令,并没区别;这个主要看个人喜好,个人喜欢用小写字母,主要是为了和变量区分开来,因为 cmake 的内置变量其名称都是使用大写字母组成的。

部分常用命令

cmake 提 供 了 很 多 命 令 , 每 一 个 命 令 都 有 它 自 己 的 功 能 、 作 用 , 通 过 这 个 链 接 地 址 cmake-commands(7) — CMake 3.5.2 Documentation 可以查询到所有的命令及其相应的介绍、使用方法等等,如下所示:

大家可以把这个链接地址保存起来,可以把它当成字典的形式在有需要的时候进行查询,由于命令非常多,笔者不可能将所有命令都给大家介绍一遍,这里给大家介绍一些基本的命令,如下表所示:

接下来详细地给大家介绍每一个命令。

add_executable

add_executable 命令用于添加一个可执行程序目标,并设置目标所需的源文件,该命令定义如下所示:

add_executable(<name> [WIN32] [MACOSX_BUNDLE] [EXCLUDE_FROM_ALL] source1 [source2 ...])

该命令提供了一些可选参数,这些可选参数的含义笔者就不多说了,通常不需要加入,具体的含义大家可以自己查看 cmake 官方文档(add_executable — CMake 3.5.2 Documentation);只需传入目标名和对应的源文件即可,譬如:

#生成可执行文件 hello

add_executable(hello 1.c 2.c 3.c)

定义了一个可执行程序目标 hello,生成该目标文件所需的源文件为 1.c、2.c 和 3.c。需要注意的是,源文件路径既可以使用相对路径、也可以使用绝对路径,相对路径被解释为相对于当前源码路径(注意,这里源码指的是 CMakeLists.txt 文件,因为 CMakeLists.txt 被称为 cmake 的源码,若无特别说明,后续将沿用这个概念!)。

add_library

add_library 命令用于添加一个库文件目标,并设置目标所需的源文件,该命令定义如下所示:

add_library(<name> [STATIC | SHARED | MODULE] [EXCLUDE_FROM_ALL] source1 [source2 ...])

第一个参数 name 指定目标的名字,参数 source1…source2 对应源文件列表;add_library 命令默认生成的库文件是静态库文件,通过 SHARED 选项可使其生成动态库文件,具体的使用方法如下:

#生成静态库文件 libmylib.a
add_library(mylib STATIC 1.c 2.c 3.c)#生成动态库文件 libmylib.so
add_library(mylib SHARED 1.c 2.c 3.c)

与 add_executable 命令相同,add_library 命令中源文件既可以使用相对路径指定、也可以使用绝对路径指定,相对路径被解释为相对于当前源码路径。

不管是 add_executable、还是 add_library,它们所定义的目标名在整个工程中必须是唯一的,不可出现两个目标名相同的目标。

add_subdirectory

……

更多直接百度或者查看正点原子的手册吧,不一一摘录了。

变量(variable)

在 CMakeLists.txt 文件中可以使用变量,使用 set 命令可以对变量进行设置,譬如:

设置变量 MY_VAL

set(MY_VAL "Hello World!")

上例中,通过 set 命令对变量 MY_VAL 进行设置,将其内容设置为"Hello World!";那如何引用这个变量呢?这与 Makefile 是相同的,通过${MY_VAL}方式来引用变量,如下所示:

#设置变量 MY_VAL

set(MY_VAL "Hello World!")

#引用变量 MY_VAL

message(${MY_VAL})

变量可以分为 cmake 内置变量以及自定义变量,譬如上例中所定义的 MY_VAL 就是一个自定义变量;譬如在 32.3.5 小节中所使用的 LIBRARY_OUTPUT_PATH 和 EXECUTABLE_OUTPUT_PATH 变量则是cmake 的内置变量,每一个内置变量都有自己的含义,像这样的内置变量还有很多,稍后向大家介绍。

部分常用变量

变量也是 cmake 中的一个重头戏,cmake 提供了很多内置变量,每一个变量都有它自己的含义,通过这个链接地址 cmake-variables(7) — CMake 3.5.2 Documentation 可以查询到所有的内置变量及其相应的介绍,如下所示:

在这一份文档中,对变量进行分类,分为:提供信息的变量、改变行为的变量、描述系统的变量、控制编译的变量等等,笔者也按照这个分类给大家介绍一些基本、常用的变量。

提供信息的变量

顾名思义,这种变量可以提供某种信息,既然如此,那么我们通常只需要读取变量即可,而不需要对变量进行修改:

改变行为的变量

顾名思义,意味着这些变量可以改变某些行为,所以我们可以通过对这些变量进行设置以改变行为。

描述系统的变量

顾名思义,这些变量描述了系统相关的一些信息:

控制编译的变量

这些变量可以控制编译过程,具体如下所示:

更多直接参考正点原子手册或者自行百度。

按需要另外自行学习即可。

双引号的作用

CMake 中,双引号的作用我们可以从两个方面进行介绍,命令参数和引用变量。

命令参数

调用命令时,参数可以使用双引号,譬如:

project("HELLO")

也可以不使用双引号,譬如:

project(HELLO)

那它们有什么区别呢?在本例中是没有区别的,命令中多个参数之间使用空格进行分隔,而 cmake 会将双引号引起来的内容作为一个整体,当它当成一个参数,假如你的参数中有空格(空格是参数的一部分),那么就可以使用双引号,如下所示:

message(Hello World)
message("Hello World")

在这个例子中,第一个 message 命令传入了两个参数,而第二个 message 命令只传入一个参数;在第一个 message 命令中,打印信息时,会将两个独立的字符串 Hello 和 World 都打印出来,而且 World 会紧跟在Hello 之后,如下:

HelloWorld

而第二个 message 命令只有一个参数,所以打印信息如下:

Hello World

这就是双引号在参数中的一个作用。

引用变量

我们先来看个例子,如下所示:

CMakeLists.txt

set(MY_LIST Hello World China)
message(${MY_LIST})

这个例子的打印信息如下:

HelloWorldChina

在这个例子中,MY_LIST 是一个列表,该列表包含了 3 个元素,分别是 Hello、World、China。但这个message 命令打印时却将这三个元素全部打印出来,并且各个元素之间没有任何分隔。此时我们可以在引用变量(${MY_LIST})时加上双引号,如下所示:

CMakeLists.txt

set(MY_LIST Hello World China)
message("${MY_LIST}")

此时 message 打印信息如下:

Hello;World;China

因为此时${MY_LIST}是一个列表,我们用"${MY_LIST}"这种形式的时候,表示要让 CMake 把这个数组的所有元素当成一个整体,而不是分散的个体。于是,为了保持数组的含义,又提供一个整体的表达方式,CMake 就会用分号“;”把这数组的多个元素连接起来。而如果不加双引号时,CMake 不会数组当成一个整体看待,而是会将数组中的各个元素提取出进行打印输出。

条件判断

在 cmake 中可以使用条件判断,条件判断形式如下:

else 和 endif 括号中的<expression>可写可不写,如果写了,就必须和 if 中的<expression>一致。

expression 就是一个进行判断的表达式,表达式对照表如下:

上 表 中 只是 列 出其 中一 部 分 表达 式 ,还 有其 它 一 些表 达 式这 里并 未 列 出, 大 家可 以通 过if — CMake 3.5.2 Documentation 这个链接地址进行查看。

老规矩,更多自行百度或者参考正点原子手册。

循环语句

cmake 中除了 if 条件判断之外,还支持循环语句,包括 foreach()循环、while()循环。

一、foreach 循环

①、foreach 基本用法

foreach 循环的基本用法如下所示:

endforeach 括号中的<loop_var>可写可不写,如果写了,就必须和 foreach 中的<loop_var>一致。

参数 loop_var 是一个循环变量,循环过程中会将参数列表中的变量依次赋值给他,类似于 C 语言 for 循环中经常使用的变量 i。

foreach 循环测试

foreach(loop_var A B C D)message("${loop_var}")
endforeach()

打印信息为:

A
B
C
D

使用 foreach 可以编译一个列表中的所有元素,如下所示:

foreach 循环测试

set(my_list hello world china)foreach(loop_var ${my_list})message("${loop_var}")
endforeach()

打印信息如下:

②、foreach 循环之 RANGE 关键字

用法如下所示:

foreach(loop_var RANGE stop)
foreach(loop_var RANGE start stop [step])

对于第一种方式,循环会从 0 到指定的数字 stop,包含 stop,stop 不能为负数。

而对于第二种,循环从指定的数字 start 开始到 stop 结束,步长为 step,不过 step 参数是一个可选参数,如果不指定,默认 step=1;三个参数都不能为负数,而且 stop 不能比 start 小。

接下来我们进行测试,测试一:

foreach 循环测试

foreach(loop_var RANGE 4)message("${loop_var}")
endforeach()

打印信息如下:

测试二:

foreach 循环测试

foreach(loop_var RANGE 1 4 1)message("${loop_var}")
endforeach()

打印信息如下:

③、foreach 循环之 IN 关键字

用法如下:

foreach(loop_var IN [LISTS [list1 [...]]] [ITEMS [item1 [...]]])

循环列表中的每一个元素,或者直接指定元素。

接下来进行测试,测试一:

foreach 循环测试

set(my_list A B C D)foreach(loop_var IN LISTS my_list)message("${loop_var}")
endforeach()

打印信息如下:

测试二:

foreach 循环测试

foreach(loop_var IN ITEMS A B C D)message("${loop_var}")
endforeach()

打印信息同上。

二、while 循环

while 循环用法如下:

endwhile 括号中的 condition 可写可不写,如果写了,就必须和 while 中的 condition 一致。

cmake 中 while 循环的含义与 C 语言中 while 循环的含义相同,但条件 condition 为真时,执行循环体中的命令,而条件 condition 的语法形式与 if 条件判断中的语法形式相同。

while 循环测试

set(loop_var 4)while(loop_var GREATER 0)message("${loop_var}")math(EXPR loop_var "${loop_var} 1")
endwhile()

输出结果如下:

上例中,while 循环的条件是(loop_var GREATER 0),等价于(loop_var > 0),当 loop_var 变量的有效数值大于 0 时,执行 while 循环体;在 while 循环体中使用到了 cmake 中的数学运算命令 math(),关于数学运算下小节会向大家介绍。

在 while 循环体中,打印 loop_var,之后将 loop_var 减一。

三、break、continue

cmake 中,也可以在循环体中使用类似于 C 语言中的 break 和 continue 语句。

①、break

break()命令用于跳出循环,和在 C 语言中的作用是一样的,测试如下:

打印信息如下:

整个代码笔者就不再解释了,注释已经写得很清楚了!

②、continue

continue()命令用于结束本次循环,执行下一次循环,测试如下:

这段 cmake 代码是求 0 到 10 之间的偶数(左闭右开),并将偶数打印出来,使用到了 continue()命令,代码不再解释,注释已经写得很清楚了。

打印结果如下:

关于 break()和 continue()命令的使用就介绍到这里了。

数学运算 math

在 cmake 中如何使用数学运算呢?其实,cmake 提供了一个命令用于实现数学运算功能,这个命令就是 math(),如下所示:

math(EXPR <output variable> <math expression>)

math 命令中,第一个参数是一个固定的关键字 EXPR,第二个参数是一个返回参数,将数学运算结果存放在这个变量中;而第三个参数则是一个数学运算表达式,支持的运算符包括:+(加)、-(减)、*(乘)、/(除)、%(求余)、|(按位或)、&(按位与)、^(按位异或)、~(按位取反)、<<(左移)、>>(右移)以及这些运算符的组合运算,它们的含义与 C 语言中相同。

譬如:

math(EXPR out_var "1+1") #计算 1+1
math(EXPR out_var "100 * 2") ##计算 100x2
math(EXPR out_var "10 & 20") #计算 10 & 20

我们进行测试:

math()命令测试

math(EXPR out_var "100 + 100")
message("${out_var}")math(EXPR out_var "100 - 50")
message("${out_var}")math(EXPR out_var "100 * 100")
message("${out_var}")math(EXPR out_var "100 / 50")
message("${out_var}")math(EXPR out_var "(100 & 100) * 50 - 2")
message("${out_var}")

测试结果如下:

定义函数

在 cmake 中我们也可以定义函数,cmake 提供了 function()命令用于定义一个函数,使用方法如下所示:

endfunction 括号中的<name>可写可不写,如果写了,就必须和 function 括号中的<name>一致。

①、基本使用方法

第一个参数 name 表示函数的名字,arg1、arg2…表示传递给函数的参数。调用函数的方法其实就跟使用命令一样,一个简单地示例如下所示:

打印信息如下:

②、使用 return()命令

在 function()函数中也可以使用 C 语言中的 return 语句退出函数,如下所示:

执行结果如下:

只打印了 Hello,并没有打印 World,说明 return()命令是生效的,执行 return()命令之后就已经退出当前函数了,所以并不会打印 World。但是需要注意的是,return 并不可以用于返回参数,那函数中如何返回参数给调用者呢?关于这个问题,后续再给大家讲解,因为这里涉及到其它一些问题,本小节暂时先不去理会这个问题。

③、可变参函数

在 cmake 中,调用函数时实际传入的参数个数不需要等于函数定义的参数个数(甚至函数定义时,参数个数为 0),但是实际传入的参数个数必须大于或等于函数定义的参数个数,如下所示:

函数 xyz 定义时只有一个参数,但是实际调用时我们传入了 3 个参数,注意这并不会报错,是符合function()语法规则的,会正常执行,打印信息如下:

从打印信息可知,message()命令打印出了调用者传入的第一个参数,也就是 Hello。

这种设计有什么用途呢?正如我们的标题所言,这种设计可用于实现可变参函数(与 C 语言中的可变参数函数概念相同);但是有个问题,就如上例中所示,用户传入了 3 个参数,但是函数定义时并没有定义这些形参,函数中如何引用到第二个参数 World 以及第三个参数 China 呢?其实 cmake 早就为大家考虑到了,并给出了相应的解决方案,就是接下来向大家介绍的内部变量。

④、函数的内部变量

function()函数中可以使用内部变量,所谓函数的内部变量,指的就是在函数内部使用的内置变量,这些内部变量如下所示:

我们可以进行测试:

源码执行结果如下:

这个大家自己去对照一下就知道了。

更多自行百度吧。

宏定义

cmake 提供了定义宏的方法,cmake 中函数 function 和宏定义 macro 在某种程度上来说是一样的,都是创建一段有名字的代码可以在后面被调用,还可以传参数。通过 macro()命令定义宏,如下所示:

endmacro 括号中的<name>可写可不写,如果写了,就必须和 macro 括号中的<name>一致。参数 name表示宏定义的名字,在宏定义中也可以使用前面给大家介绍的 ARGVX(X 是一个数字)、ARGC、ARGV、ARGN 这些变量,所以这些也是宏定义的内部变量。

更多待补充。

文件操作

cmake 提供了 file()命令可对文件进行一系列操作,譬如读写文件、删除文件、文件重命名、拷贝文件、 创建目录等等,本小节我们一起来学习这个功能强大的 file()命令。

①、写文件:写、追加内容

使用 file()命令写文件,使用方式如下所示:

file(WRITE <filename> <content>...)
file(APPEND <filename> <content>...)

将<content>写入名为<filename>的文件中。如果文件不存在,它将被创建;如果文件已经存在,WRITE模式将覆盖它,APPEND 模式将内容追加到文件末尾。

测试代码如下:

注意文件可以使用绝对路径或相对路径指定,相对路径被解释为相对于当前源码路径。

执行 CMakeLists.txt 代码之后,会在当前源码目录下生成一个名为 wtest.txt 的文件。

更多待补充。

关于 cmake,笔者就给大家介绍这么多,已经基本够用了;其实还有很多的命令以及变量没有介绍到,但完全可以自己去看,然后去实战测试!

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mysql专题复习

重点内容&#xff1a;1. Mysql架构&#xff1a;客户端 Server层 存储引擎2. 索引数据结构&#xff1a;B树4. 索引优化&#xff1a;覆盖索引、排序、JOIN、分页&#xff1b; COUNT; 索引下推&#xff1b;单/双路排序5. 数据库事务&#xff1b; 锁&#xff1b;隔离级别&#xff…

CLIP的tokenizer详解

一、bytes_to_unicodedef bytes_to_unicode():"""Returns list of utf-8 byte and a corresponding list of unicode strings.The reversible bpe codes work on unicode strings.This means you need a large # of unicode characters in your vocab if you wa…

【如何判断Linux系统是Ubuntu还是CentOS】

要确定您的操作系统是 Ubuntu 还是 CentOS&#xff0c;可以通过以下方法快速检查&#xff1a; 方法 1&#xff1a;通过终端命令&#xff08;推荐&#xff09; 在终端中执行以下命令之一&#xff1a; 查看 /etc/os-release 文件 cat /etc/os-releaseUbuntu 特征&#xff1a;显示…

RISCV Linux 虚拟内存精讲系列二 -- Linux 入口 head.S

通过 Linux 的构建系统&#xff0c;即 Linux 源代码的根目录下的 Makefile&#xff0c;能够找到 vmlinux 的链接文件&#xff0c;从而能够查看其入口代码 head.S:_start&#xff0c; 如下&#xff1a; Linux 构建系统主Makefile: vmlinux.lds: head.S: 找到该入口后&#xff0c…

springAI学习:Advisors

spring AI Advisors类似于拦截器&#xff0c;会对请求的prompt做出特定的修改和增强&#xff08;比如传入历史沟通记录、搜索信息等等&#xff09;&#xff0c;以达到完善prompt的目的。通过Advisors API&#xff0c;开发人员可以创建更为复杂、可重用、可维护的AI组件。下面介…

MySQL CDC与Kafka整合指南:构建实时数据管道的完整方案

一、引言&#xff1a;现代数据架构的实时化需求 在数字化转型浪潮中&#xff0c;实时数据已成为企业的核心资产。传统批处理ETL&#xff08;每天T1&#xff09;已无法满足以下场景需求&#xff1a; 实时风险监控&#xff08;金融交易&#xff09;即时个性化推荐&#xff08;电商…

MATLAB | 绘图复刻(二十一)| 扇形热图+小提琴图

前段时间在小红书刷到了一个很有特色的热力图&#xff0c;由大佬滚筒洗衣机创作&#xff0c;感觉很有意思&#xff0c;尝试 MATLAB 复刻&#xff1a; 作者使用的是 python 代码&#xff0c;赶快去瞅瞅。 复刻效果 正文部分 0.数据准备 数据需要一个用来画热图的矩阵以及一个…

批量PDF转换工具,一键转换Word Excel

软件介绍 今天为大家推荐一款高效的Office文档批量转换工具&#xff0c;能够快速将Word和Excel文件批量转换为PDF格式。 软件特点 这款名为"五五Excel word批量转PDF"的工具体积小巧&#xff0c;不到2M大小&#xff0c;却能实现强大的批量转换功能&#xff0c…

面试150 基本计算器

思路 利用栈&#xff08;stack&#xff09;来保存进入括号前的计算状态&#xff08;包括当前计算结果和符号&#xff09;&#xff0c;以便在括号结束后正确恢复计算上下文。代码通过遍历字符串&#xff0c;识别数字、加号、减号和括号。遇到数字时构造完整数值&#xff1b;遇到…

源哈希(sh)解析

源哈希&#xff08;Source Hashing&#xff09;是一种负载均衡算法&#xff0c;它根据请求的源 IP 地址&#xff08;或其他标识符&#xff09;生成哈希值&#xff0c;然后根据这个哈希值将请求分配到特定的后端服务实例。这种方法常用于确保来自同一客户端的请求始终被路由到同…

axios的使用以及封装

前言&#xff1a; 在现代前端开发中&#xff0c;网络请求是不可避免的核心功能之一。无论是获取后端数据、提交表单信息&#xff0c;还是与第三方 API 交互&#xff0c;高效且可靠的 HTTP 请求库至关重要。axios 作为一款基于 Promise 的 HTTP 客户端&#xff0c;凭借其简洁的 …

github上部署自己的静态项目

前置知识1、要在github部署项目要提交打包后的静态文件(html,css&#xff0c;js)到仓库里2、我们看下github所提供给我们的部署方式有啥&#xff0c;如下所见&#xff1b;要么是/root文件夹&#xff08;就说仓库里全是打包后的产物&#xff1a;html,css&#xff0c;js要全部放到…

能源管理综合平台——分布式能源项目一站式监控

综合性的能源企业管理面临着项目多、分布散、信息孤岛等问题&#xff0c;分布式的多项目能源在线监控管理平台是一种集成了多个能源项目的数据采集、监控、分析和管理的系统。平台集成GIS能力&#xff0c;能够展示项目的整体分布态势&#xff0c;对不同地点、不同类型的能源项目…

修改阿里云vps为自定义用户登录

win系统上找到控制面板-->用户账户-->更改账户类型点击更改账户类型&#xff0c;此时我们看到vps的默认管理员账户Administrator。为了防止vps被别人使用默认账户Administrator攻击&#xff0c;我们添加一个用户账户&#xff0c;点击添加用户账户。 用户名建议奇葩点&…

Linux: perf: debug问题一例,cpu使用率上升大约2%;多线程如何细化cpu及perf数据分析

文章目录 前提面临的问题内核级别函数的差别继续debug总结根据pid前提 一个进程安置在一个CPU上,新功能上线之后,固定量的业务打起来,占用的CPU是42%。之前没有新功能的情况下,CPU占用是40%。差了大约2%。而且这个进程里的线程数非常多,有50多个线程。从差距看变化不大,…

计算阶梯电费

实现一个 Python 程序&#xff0c;根据使用的电量&#xff08;从控制台中让用户输入&#xff09;计算需要交的电费&#xff0c;电量分为两个阶梯&#xff0c;小于 200 度和大于 200 度&#xff0c;如果电量小于等于 200 度&#xff0c;电价就是 0.5 元/度&#xff0c;如果电量大…

替代MT6701,3D 霍尔磁性角度传感器芯片

KTH5502 是一款基于垂直霍尔技术的高精度绝对角度传感器芯片&#xff0c;支持全角度&#xff08;0–360&#xff09;测量。 芯片内部集成 X、Y 轴的垂直霍尔元件和 Z 轴的水平霍尔元件&#xff0c;能够同时感知磁场在 X、Y、Z 三个 方向的变化。得益于垂直霍尔技术优异的正交匹…

华为 Mate 80 影像配置揭秘:硬软双升

7 月 7 日&#xff0c;知名数码博主爆料了华为 Mate 80 系列的影像配置&#xff0c;引发广泛关注。从曝光信息来看&#xff0c;Mate 80 系列在影像方面延续华为的技术探索&#xff0c;通过硬件升级与算法优化&#xff0c;力图为用户带来更出色的拍摄体验。​ 爆料显示&#xff…

Android studio升级AGP需要注意哪些

deep seek回答&#xff1a; 深度思考完成 用时26秒 嗯&#xff0c;用户询问的是在Android Studio中升级AGP需要注意哪些事项。这个问题很实用&#xff0c;因为AGP升级确实是个容易踩坑的过程。让我看看搜索结果里有什么关键信息。 首先注意到搜索结果里有几个高可信度的资料专…

MapReduce数据处理过程2万字保姆级教程

目录 1. MapReduce 的核心思想:分而治之的艺术 2. Hadoop MapReduce 的架构:从宏观到微观 3. WordCount 实例:从代码到执行的完整旅程 4. 源码剖析:Job.submit 的魔法 5. Map 任务的执行:从分片到键值对 6. Shuffle 阶段:MapReduce 的幕后英雄 7. Reduce 任务的执行…