RPM 打包入门(基于openEuler)

news2024/11/25 21:43:23

主要参考内容(均为官方文档):

https://rpm-packaging-guide.github.io/#building-rpms
https://docs.redhat.com/zh_hans/documentation/red_hat_enterprise_linux/8/html/packaging_and_distributing_software/introduction-to-rpm_packaging-and-distributing-software#introduction-to-rpm_packaging-and-distributing-software

本文的环境:WSL2 + Qemu + OpenEuler24.03
提到的所有示例,均在该环境下测试

一、快速了解

RPM Package Manager (RPM)是一个运行在 Red Hat Enterprise Linux (RHEL)、CentOS 和 Fedora 上的软件包管理系统。您可以使用 RPM 为任何这些操作系统所创建的软件进行分发、管理和更新。

在 Red Hat Enterprise Linux 中,RPM 完全集成到更高级别的软件包管理软件中,如 YUM 或 PackageKit。虽然 RPM 提供了自己的命令行界面,但大多数用户只需要通过这个软件与 RPM 进行交互。但是,在构建 RPM 软件包时,您必须使用 RPM 工具,如 rpmbuild (8) 。

具体来说,RPM 软件包包含以下部分:

  • GPG 签名:GPG 签名用于验证软件包的完整性。
  • 标头(软件包元数据):RPM 软件包管理器使用此元数据来确定软件包依赖项、安装文件的位置及其他信息。
  • payload:有效负载是一个 cpio 归档,其中包含要安装到系统的文件。
    RPM 软件包有两种类型。这两种类型都共享文件格式和工具,但内容不同,并实现不同的目的:
  • 源 RPM(SRPM):SRPM 包含源代码和 spec 文件,它描述了如何将源代码构建为二进制 RPM。另外,SRPM 可以包含源代码的补丁。
  • 二进制 RPM:一个二进制 RPM 包含了根据源代码和补丁构建的二进制文件。
    安装 rpmdevtools 软件包:

openEuler 中使用 dnf,其他系统中可能使用 yum 安装:

dnf install rpmdevtools*

二、前置知识

这里仅简要罗列,更详细的内容可从文章开头的参考链接中查看
可以选择跳过,直接查看第三章的示例

1、源代码
源代码是人类可读的计算机指令,其描述了如何执行计算。源代码是使用编程语言表达的。

2、机器码
源代码转换为机器码方法:

  • 原生编译软件
    原生编译的软件是独立软件、原生编译的 RPM 软件包是特定于架构的,例如 C 语言
  • 使用语言解释器或语言虚拟机解释软件,可以使用原始解释或字节编译软件
    完全使用解释编程语言编写的软件不是特定于架构的。因此,生成的 RPM 软件包在其名称中有 noarch 字符串
    • 原始解释的软件:不需要编译这类软件,原始解释的软件由解释器直接执行
    • 字节编译的软件:必须首先将这类软件编译成字节码,然后由语言虚拟机执行

3、构建方式
在软件构建过程中,源代码被转换为可以使用 RPM 打包的软件工件

  • 原生编译的代码构建软件,使用以下方法之一将使用编译语言编写的软件构建成可执行文件:
    • 手动构建(使用 gcc 命令)
    • 自动化构建(使用 Makefile 文件与 make 命令)
  • 将解释编程语言编写的源代码转换为机器码:
    • 字节编译
    • 原始解释(例如 Shell 脚本)
      Python 支持原始解释、字节编译两种方式,字节编译的版本速度更快。因此,RPM 软件包程序更喜欢将字节编译的版本打包,来分发给最终用户。

4、修复软件(打补丁)
在打包软件时,可能需要对原始源代码进行某些更改,如修复 bug 或更改配置文件。在 RPM 打包中,可以将原始源代码保持不变,并在其上应用补丁。
补丁是更新源代码文件的一段文本。补丁具有 diff 格式,因为它代表文本的两个版本之间的区别。可以使用 diff 实用程序创建补丁,然后使用 patch 实用程序将补丁应用到源代码。

5、LICENSE
软件许可证文件(LICENSE)告知用户他们可以使用源代码做什么和不能做什么。
没有源代码许可证意味着您保留此代码的所有权限,任何人都不能从源代码复制、分发或创建衍生工作。
GPLv3 LICENSE 示例:

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

6、源代码存档(归档文件)
归档文件是带有 .tar.gz 或 .tgz 后缀的文件。将源代码放入存档中是发布软件以稍后打包为分发的常用方法。
注意:补丁 文件不随程序一起在存档中分发。构建 RPM 时,RPM 软件包管理器应用补丁。补丁将与 tar.gz 存档一起放在 ~/rpmbuild/SOURCES/ 目录中。
LICENSE 和源代码是一起归档的,而 patch 不和源代码一起归档,即 .tar.gz 归档文件中包含 LICENSE 和源代码,patch 和 .tar.gz 并列存放在 ~/rpmbuild/SOURCES 目录下

# 源代码文件夹
mkdir cello-1.0
mv cello.c cello-1.0/
mv Makefile cello-1.0/
mv LICENSE cello-1.0/

# 进行压缩打包,创建存档
tar -cvzf cello-1.0.tar.gz cello-1.0

# 移动到 ~/rpmbuild/SOURCES/ 目录中, 存储用于构建软件包的源文件的默认目录
# 对于需要 patch 的软件包,将所需的 patch 也移动到 ~/rpmbuild/SOURCES/ 目录中
mv cello-1.0.tar.gz ~/rpmbuild/SOURCES/

三、打包 Hello World 示例

0、设置工作区

# 1. 安装 rpmdevtools 软件包
dnf install rpmdevtools
# 2. 执行 rpmdev-setuptree 程序
rpmdev-setuptree
# 默认在 ~ 目录下创建 rpmbuild 文件夹
tree ~/rpmbuild/

RPM 打包工作区目录:

1、spec 文件

spec 文件是一个文件,其中包含 rpmbuild 实用程序用来构建 RPM 软件包的指令。此文件通过在一系列部分中定义指令,为构建系统提供必要信息。这些部分在 spec 文件的 Preamble 和 Body 部分中定义:

  • Preamble 部分包含一系列在 Body 部分中使用的元数据项。
  • Body 部分代表指令的主要部分。

列举了 Preamble 部分关键的指令:
暂时无法在飞书文档外展示此内容
列举 Body 中部分重要的项目:
暂时无法在飞书文档外展示此内容

2、BuildRoots

在 RPM 打包上下文中,buildroot 是 chroot 环境。构建工件通过使用与最终用户系统中将来层次结构相同的文件系统层次结构放在此,buildroot 充当根目录。构建工件的放置必须遵循最终用户系统的文件系统层次结构标准。
buildroot 中的文件稍后放入 cpio 存档,后者成为 RPM 的主要部分。当在最终用户的系统中安装 RPM 时,这些文件将提取到 root 目录中,保留正确的层次结构。

# 对于不熟悉的宏,可以使用 rpm --eval 查看内容
rpm --eval %{_bindir}
# 输出:/usr/bin

3、使用 spec 文件

要打包新软件,必须创建一个 spec 文件。通过以下任一方法创建 spec 文件:

  • 从头开始手动编写新的 spec 文件。
  • 使用 rpmdev-newspec 工具。这个工具会创建一个未填充的 spec 文件,其中会填写必要的指令和字段。
cd ~/rpmbuild/SPECS

# 创建空的 spec 文件
rpmdev-newspec bello    # hello world     Bash版本
rpmdev-newspec cello    # hello world     C版本
rpmdev-newspec pello    # hello world     python版本

填充 spec 文件流程:

  1. 打开 rpmdev-newspec 创建的 ~/rpmbuild/SPECS/.spec 文件
  2. 填充 spec 文件的 Preamble 部分的指令:
    • Name:已指定为 rpmdev-newspec 的参数
    • Version:设置为与源代码的上游版本匹配
    • Release:自动设置为 1%{?dist},它最初是 1
    • Summary:软件包的单行说明
    • License:与源代码关联的软件许可证
    • URL:上游软件网站的 URL,为实现一致性,请使用 %{name} RPM 宏变量,并使用 https://example.com/%{name} 格式
    • Source:上游软件源代码的 URL,直接链接到被打包的软件版本
    • BuildRequires:指定软件包的构建时依赖项
    • Requires:指定软件包的运行时依赖项
    • BuildArch:指定软件架构
  3. 填充 spec 文件 Body 部分中的以下指令:可以将这些指令视为部分标题,因为这些指令可以定义多行、多结构或脚本化任务
    • %description:软件的完整描述
    • %prep:一系列命令来准备软件以进行构建
    • %build:用于构建软件的一系列命令
    • %install:一系列命令:用于指示 rpmbuild 命令如何将软件安装到 BUILDROOT 目录中
    • %files:指定在系统上安装的 RPM 软件包提供的文件列表
    • %changelog:软件包的每个 Version-Release 的 datetamped 条目列表
      从 %changelog 部分的第一行开始,带有星号(*)字符,后跟 Day-of-Week Month Day Year Name Surname - Version-Release
      对于实际更改条目,请遵循这些规则:
      • 每个更改条目都可以包含多个项目,每个代表一个改变。
      • 每个项目在新行中开始。
      • 每个项目以连字符(-)字符开头。

4、分析 bello 的 spec 文件

Bello 是使用 bash 写的 hello world,spec 文件如下

Name:           bello
Version:        0.1                --> 软件版本
Release:        1%{?dist}          --> 发布版本
Summary:        Hello World example implemented in bash script

License:        GPLv3+
URL:            https://www.example.com/%{name}    --> 软件上游网站 url
Source0:        https://www.example.com/%{name}/releases/%{name}-%{version}.tar.gz # 软件的 url

Requires:       bash              --> 运行时依赖 bash

BuildArch:      noarch            --> 与机器的体系结构无关

%description
The long-tail description for our Hello World Example implemented in
bash script.

%prep                               --> 准备阶段:例如解压缩源代码存档
%setup -q

%build                              --> 构建阶段:bash 脚本不需要构建

%install                            --> 安装阶段

mkdir -p %{buildroot}/%{_bindir}

install -m 0755 %{name} %{buildroot}/%{_bindir}/%{name}    --> 安装到指定路径

%files
%license LICENSE                      --> LICENSE
%{_bindir}/%{name}                    --> /usr/bin/bello

%changelog                            --> 改变日志
* Tue May 31 2016 Adam Miller <maxamillion@fedoraproject.org> - 0.1-1
- First bello package
- Example second item in the changelog for version-release 0.1-1
  • BuildRequires 指令指定软件包的 build-time 依赖项已被删除,因为没有可用于 bello 的构建步骤。Bash 是原始解释编程语言,文件仅安装到其系统上的位置。
  • Requires 指令指定软件包的运行时依赖项,它只包括 bash,因为 bello 脚本只需要 bash shell 环境才能执行。
  • %build 部分指定如何构建软件为空,因为不需要构建 bash 脚本。
  • %setup 对源代码存档进行解压

install:是Linux系统中用来复制文件和设置权限的命令,-m 0755:这个选项指定了安装文件的权限。0755是一个八进制数,表示文件所有者有读写执行权限(7),组用户和其他用户有读取和执行权限(5),没有写权限。
所以,整个 install 命令的作用是将名为%{name}的可执行文件复制到%{buildroot}/%{_bindir}目录下,并设置其权限为0755。在RPM打包过程中,%{buildroot}目录下的内容最终会被打包到 RPM 文件中,当用户安装RPM包时,这些文件会被安装到实际的文件系统路径上。
rpmbuild 常用的参数:
暂时无法在飞书文档外展示此内容

# 进入 SPEC 文件夹中
cd ~/rpmbuild/SPECS

# 以构建 bello 的 RPM 包为例(其他的类似)
rpmbuild -bb bello.spec

可以使用 --noclean 留下构建的过程文件,在 BUILD/BUILDROOT 中可以看到 build 时做了什么
默认在构建好 rpm 包时,BUILD/BUILDROOT 下的内容会被清理

5、分析 pello 的 spec 文件

Pello 是使用 python 写的 hello world 程序

注:以下 spec 文件无法再 python3 上使用,python2 下应该是可以正确使用的【未验证】
在 python3 中,python -m compile 会将生成的pyc字节码文件放到 pycache 文件夹下,并且会修改命名,与该 spec 文件不匹配。而在 python2 中,生成的 pyc 字节码文件,可以按照以下 spec 描述进行。

Name:           pello
Version:        0.1.1
Release:        1%{?dist}
Summary:        Hello World example implemented in Python

License:        GPLv3+
URL:            https://www.example.com/%{name}
Source0:        https://www.example.com/%{name}/releases/%{name}-%{version}.tar.gz

BuildRequires:  python        --> 构建生成 pyc 字节码时,需要使用 python 
Requires:       python        --> 运行时需要使用 python
Requires:       bash          --> 运行时需要 bash

BuildArch:      noarch

%description
The long-tail description for our Hello World Example implemented in Python.

%prep                            --> 准备阶段:
%setup -q                        --> 解压源代码存档文件

%build                            --> 构建阶段:

python -m compileall %{name}.py   --> build 阶段, 对 py 进行编译, 得到字节码

%install                                   --> 安装阶段:

mkdir -p %{buildroot}/%{_bindir}               --> 递归创建目录
mkdir -p %{buildroot}/usr/lib/%{name}

cat > %{buildroot}/%{_bindir}/%{name} <<EOF    --> 创建切入bash脚本,命名为 pello
#!/bin/bash
/usr/bin/python /usr/lib/%{name}/%{name}.pyc    --> 使用 python 执行 pyc
EOF

chmod 0755 %{buildroot}/%{_bindir}/%{name}     --> 修改切入bash脚本的权限 

install -m 0644 %{name}.py* %{buildroot}/usr/lib/%{name}/   --> 将源 py 文件安装到 /usr/lib 中

%files
%license LICENSE                    --> LICENSE
%dir /usr/lib/%{name}/              --> /usr/lib/pello 目录
%{_bindir}/%{name}                  --> /usr/bin/pello 下的新建的切入脚本
/usr/lib/%{name}/%{name}.py*        --> /usr/lib/pello 目录下的 pyc 字节码文件

%changelog
* Tue May 31 2016 Adam Miller <maxamillion@fedoraproject.org> - 0.1.1-1
  - First pello package
  • Requires 指令指定软件包的运行时依赖项,其中包括两个软件包:
    • 在运行时执行字节代码所需的 python 软件包。
    • 执行小入口点脚本所需的 bash 软件包。
  • BuildRequires 指令指定软件包的 build-time 依赖项,它只包括 python 软件包。pello 程序需要 python 执行字节型构建流程。
  • %build 部分指定如何构建软件,创建脚本的字节版本。请注意,在实际打包中,通常会根据所使用的发行版自动执行。
  • %install 部分与这个事实对应,您必须将字节文件安装到系统上的库目录中,以便可以访问它。
    创建打包程序脚本的示例显示了 spec文件本身可以脚本化。

7、分析 cello 的 spec 文件

cello 是使用 C语言编写的 hello world 示例程序,并且使用补丁 patch 进行修复

注:个人实验过程中,%prep 部分使用官方提供的示例,应用补丁会有错误,未进行解决
应用补丁的 cello 版本实验可能应用不成功

Name:           cello
Version:        1.0
Release:        1%{?dist}
Summary:        Hello World example implemented in C

License:        GPLv3+
URL:            https://www.example.com/%{name}
Source0:        https://www.example.com/%{name}/releases/%{name}-%{version}.tar.gz

Patch0:         cello-output-first-patch.patch        --> 需要使用的补丁

BuildRequires:  gcc            --> 构建时需要 gcc
BuildRequires:  make           --> 自动化构建需要 make

%description
The long-tail description for our Hello World Example implemented in
C.

%prep                   --> 准备阶段:
%setup -q               --> 解压源码等

%patch0                 --> 应用补丁到源码(属于准备阶段)

%build                  --> 构建阶段:
make %{?_smp_mflags}    --> %{?_smp_mflags} 表示 -j4 等,加速编译

%install
%make_install           --> 调用 make install

%files
%license LICENSE        --> LICENSE
%{_bindir}/%{name}      --> 可执行文件

%changelog
* Tue May 31 2016 Adam Miller <maxamillion@fedoraproject.org> - 1.0-1
- First cello package

Makefile 文件中指定如何编译、clean,以及 install

# cello 的 Makefile 文件
cello:
        gcc -g -o cello cello.c

clean:
        rm cello

install:
        mkdir -p $(DESTDIR)/usr/bin                       --> 递归创建目录
        install -m 0755 cello $(DESTDIR)/usr/bin/cello    --> 安装到指定路径

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

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

相关文章

用Python设置Excel工作表网格线的隐藏与显示

Excel表格界面的直观性很大程度上得益于表格中的网格线设计&#xff0c;这些线条帮助用户精确对齐数据&#xff0c;清晰划分单元格。网格线是Excel界面中默认显示的辅助线&#xff0c;用于辅助定位&#xff0c;与单元格边框不痛&#xff0c;不影响打印输出。然而&#xff0c;在…

Spring的启动扩展点机制详解

在Java的世界中&#xff0c;我们知道Spring是当下最主流的开发框架&#xff0c;没有之一。而在使用Dubbo、Mybatis等开源框架时&#xff0c;我们发现可以采用和Spring完全一样的使用方式来使用它们。 可能你在平时的使用过程中并没有意识到这一点&#xff0c;但仔细想一想&…

34 张动图:线缆,以太网与网络寻址

以太网 本地主机访服务器 以太网标准 非屏蔽双绞线&#xff08;UTP&#xff09; 电磁干扰 串扰 双绞线 真实的双绞线 线缆与引脚对齐方式 科普&#xff1a;网线每根芯的作用 引脚连接 数据传输与接收 主机直连到交换机 主机直连到主机&#xff08;或交换器&#xff09; Auto M…

C++ 矩阵的最小路径和解法

描述 给定一个 n * m 的矩阵 a&#xff0c;从左上角开始每次只能向右或者向下走&#xff0c;最后到达右下角的位置&#xff0c;路径上所有的数字累加起来就是路径和&#xff0c;输出所有的路径中最小的路径和。 数据范围: 1≤&#x1d45b;,&#x1d45a;≤5001≤n,m≤500&…

# 消息中间件 RocketMQ 高级功能和源码分析(九)

消息中间件 RocketMQ 高级功能和源码分析&#xff08;九&#xff09; 一、消息中间件 RocketMQ 源码分析&#xff1a; 同步刷盘分析 1、刷盘机制 RocketMQ 的存储是基于 JDK NIO 的内存映射机制&#xff08;MappedByteBuffer&#xff09;的&#xff0c;消息存储首先将消息追…

好用的便签是什么 电脑桌面上好用的便签

作为一名文字工作者&#xff0c;我经常需要在繁杂的思绪中捕捉灵感&#xff0c;记录下那些一闪而过的想法。在寻找一款适合电脑桌面的便签应用时&#xff0c;我偶然发现了敬业签便签软件简直是为我量身定制的&#xff0c;它不仅界面简洁&#xff0c;操作便捷&#xff0c;更重要…

前瞻展望,中国信通院即将发布“2024云计算十大关键词”

人类对于未知领域的探索欲望&#xff0c;似乎总是无穷无尽&#xff0c;而探索欲反过来推动了技术的革新与进步。今年以来&#xff0c;AI大模型成为科技领域最为确定的趋势之一。在大模型开启的AI原生时代&#xff0c;AI原生正在重构云计算的演化逻辑和发展走向&#xff0c;MaaS…

含铬废水有哪些危害?含铬废水怎么处理呢?

铬化物可以通过消化道、呼吸道、皮肤和粘膜侵人人体&#xff0c;主要积聚在肝、肾、内分泌系统和肺部。毒理作用是影响体内物质氧化、还原和水解过程&#xff0c;与核酸、核蛋白结合影响组织中的磷含量。铬化合物具有致癌作用。 铬化合物以蒸汽和粉尘的方式进入人体组织中&…

gstreamer+qt5实现简易视频播放器

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、安装环境1.QT52.gstreamer 二、代码1.Windows实现 三、测试效果总结 前言 最近在研究mpp&#xff0c;通过gstreamer实现了硬解码&#xff0c;但是我在想我…

ip地址怎么写才是的对的?合法ip地址正确的格式

IP地址怎么写才是的对的&#xff1f;在互联网的世界里&#xff0c;IP地址就像是我们生活中的门牌号码&#xff0c;它是每个设备在网络中的唯一标识。正确的书写IP地址对于确保网络通信的顺畅至关重要。本文将带您了解合法IP地址的正确格式与书写规范&#xff0c;并深入探讨其在…

【MySQL】索引的原理及其使用

文章目录 什么叫索引减少磁盘IO次数缓存池(Buffer Pool&#xff09;MySQL的页页内目录页目录 正确理解索引结构为什么Innodb的索引是B树结构各种存储引擎支持的索引聚簇索引和非聚簇索引索引类型 关于索引的操作创建主键索引唯一索引的创建普通索引的创建查看索引删除索引 什么…

6月21日(周五)AH股总结:沪指失守3000点,恒生科技指数跌近2%,多只沪深300ETF午后量能显著放大

内容提要 沪指全天围绕3000点关口来回拉锯&#xff0c;收盘跌破3000点。白酒及光刻机概念集体走低&#xff0c;中芯国际港股跌超2%。CRO医药概念及水利股逆势走强。 A股低开低走 沪指全天围绕3000点关口来回拉锯&#xff0c;收盘跌破3000点&#xff0c;跌0.24%。深成指跌0.04…

如何在 MySQL 中创建和使用事务?

目录 1. 环境准备 2. 创建事务 3. 事务执行 4. 事务撤消 5. 总结 事务是数据库区别于文件系统的重要特征之一&#xff0c;当我们有了事务就会让数据库始终保持一致&#xff0c;同时我们还能通过事务机制恢复到某个时间点&#xff0c;这样可以保证已提交到数据库的修改不会…

【Linux】基础IO_2

文章目录 六、基础I/O2. 系统文件I/O磁盘的存储结构 未完待续 六、基础I/O 2. 系统文件I/O 磁盘的存储结构 系统中不是所有对文件都是打开的状态&#xff0c;大部分的文件都是没有被打开的。这些文件一般都被存储在磁盘当中。磁盘通过柱面&#xff0c;扇面&#xff0c;扇区确…

JS 【详解】树的遍历(含深度优先遍历和广度优先遍历的算法实现)

用 js 描述树 let tree [{label:a,children:[{label:b,children:[{label:d},{label:e}]},{label:c,children:[{label:f}]}]} ]使用数组是因为树的节点有顺序 深度优先遍历 从根节点出发&#xff0c;优先遍历最深的节点 遍历顺序为 abdecf function DFS(tree) {tree.forEach(…

c++编译器优化不显示拷贝构造函数

一.错误情景&#xff08;无法打印拷贝函数&#xff09; #include<iostream> using namespace std;class person { public:person(){cout << "person默认构造函数调用" << endl;}person(int age){cout << "有参构造函数调用" <…

IIS代理配置-反向代理

前后端分离项目&#xff0c;前端在开发中使用proxy代理解决跨域问题&#xff0c;打包之后无效。 未配置前无法访问 部署环境为windows IIS&#xff0c;要在iis设置反向代理 安装代理模块 需要在iis中实现代理&#xff0c;需要安装Application Request Routing Cache和URL重…

在Verilog HDL中使用任务(task)

代码&#xff1a; sort4.v module sort4(ra,rb,rc,rd,a,b,c,d);output[3:0] ra,rb,rc,rd;input[3:0] a,b,c,d;reg[3:0] ra,rb,rc,rd;reg[3:0] va,vb,vc,vd;always (a or b or c or d)begin{va,vb,vc,vd}{a,b,c,d};sort2(va,vc); //va 与vc互换。sort2(vb,vd);…

为什么在React中一定要使用setState来更新数据?

为什么在React中一定要使用setState来更新数据&#xff1f; 因为我们修改了State后&#xff0c;我们希望看到React更具最新的State来重新渲染界面&#xff0c;但是这种方式修改的React并不知道数据发送的改变&#xff1b; 在React中并没有使用像Vue3或者Vue2中的数据劫持来监…

时间?空间?复杂度??

1.什么是时间复杂度和空间复杂度&#xff1f; 1.1算法效率 算法效率分析分为两种&#xff1a;第一种是时间效率&#xff0c;第二种是空间效率。时间效率被称为时间复杂度&#xff0c;而空间效率被称为空间复杂度。 时间复杂度主要衡量的是一个算法的运行速度&#xff0c;而空…