麒麟软件产品专区:https://product.kylinos.cn
开发者专区:https://developer.kylinos.cn
文档中心:https://document.kylinos.cn
摘要
软件包依赖是软件包关系的一种,它指的是一个软件包为正常运行所必须安装的其他软件包或库。如果这些依赖缺失,程序可能无法执行或会出现严重问题。因此,仅当所有依赖的软件包或库都正常安装后该软件包才被允许安装和运行程序。
依赖关系对于软件包来说是至关重要的,其在确保软件功能的完整性和性能、维护系统稳定、简化软件安装和升级过程、促进软件生态的健康发展、提高软件的安全性等方面发挥重要作用。
银河麒麟操作系统介绍
在本文中,将以 银河麒麟桌面操作系统V10 SP1作为基础编译环境进行讨论。
银河麒麟桌面操作系统V10 SP1是一款适配国产软硬件平台并深入优化和创新的新一代图形化桌面操作系统,同源支持国内外主流处理器架构,并不断使能GPU、桥片、网卡等各种新硬件,提供更优的软硬件兼容性和广泛的应用生态支持。
作为中国领先的自主创新操作系统,其基于Linux的底层架构、深度优化的自主技术以及对国产硬件平台的全面支持,使其成为了国产操作系统中的佼佼者,为国家信息安全和产业发展提供了坚实的基础,被广泛应用于各类关键行业和领域,正在成为中国企业数字化转型过程中的重要技术支撑。
为什么引入依赖而非自包含?
银河麒麟操作系统在软件包的设计方案选取时,选择使用依赖管理而非自包含模型,主要是出于以下考虑:
-
减少重复和资源浪费:通过依赖其他已存在的库或框架,可以避免在每个软件中重复相同的代码或功能,从而减少磁盘空间的占用和运行时资源的消耗。
-
提高开发效率和软件质量:使用成熟的外部库可以加快开发进程,并借助外部库的优化和测试来提升软件的稳定性和性能。
-
易于维护和更新:当依赖的库需要更新或修复时,只需更新库本身而非每个单独的应用程序,这大大简化了维护工作,并确保所有依赖该库的软件都能从中受益。
-
促进模块化和可扩展性:依赖管理支持模块化设计,使得软件项目更容易扩展和修改,同时也便于管理大型项目中的组件依赖关系。
-
安全性提升:集中管理依赖能更快速地响应安全漏洞,通过更新一个中心库来修复多个应用程序中的漏洞,从而保证了整个系统的安全性。
在本文档中,我们将在银河麒麟操作系统的基础上详细探讨软件包依赖的概念、内容以及管理方法,以帮助开发者和系统管理员理解和利用这一机制,提高系统软件的整体性能和安全性。
软件包关系
软件包依赖就是软件包关系的一种,一般用Depends
表示。
每个软件包都可以和其他软件包有各种不同的关系。除 Depends
外,还有 Recommends
、Suggests
、Pre-Depends
、Breaks
、Conflicts
、Provides
和 Replaces
,软件包管理工具(如 apt-get、aptitude、dpkg)在安装、升级或删除软件包时,会依据这些关系采取适当的操作,以确保系统的稳定性和一致性。
软件包关系说明
Depends
- 定义:此软件包仅当它依赖的软件包均已安装后才可以安装。
- 用途:指定的软件包是程序所必须的软件包,如果缺少这些依赖,程序将无法正常运行或存在严重问题。
Recommends
- 定义:推荐安装的软件包,但不是严格必须的。
- 用途:这些软件包可以增强程序功能。aptitude 和 apt-get 会在安装你的软件包时自动安装推荐的软件包,用户可以选择禁用这个行为。dpkg 会忽略此项。
Suggests
- 定义:建议安装的软件包,不是必须的。
- 用途:这些软件包可以与程序更好地协同工作,但不是必须的。所有前端程序通常不会询问是否安装建议的软件包。aptitude 可以配置为自动安装建议的软件包,但默认不会这样做。dpkg 和 apt-get 会忽略此项。
Pre-Depends
- 定义:此项中的依赖相比于
Depends
重要程度更高,仅在预依赖的软件包已安装并正确配置后,才能安装此软件包 - 用途:指定的软件包是程序安装前必须安装和配置完成的。应非常慎重使用,建议尽量避免使用此项。
- 定义:此项中的依赖相比于
Conflicts
- 定义:列出所有冲突的软件包,仅在这些软件包被删除后,当前软件包才能安装。
- 用途:当程序与某些特定软件包同时存在时无法运行或存在严重问题时使用。
Breaks
- 定义:当前软件包安装后,会破坏列出的软件包。
- 用途:通常
Breaks
会附带一个版本号说明,表示版本低于某个特定值的软件包会被破坏。软件包管理工具会选择升级这些被破坏的软件包作为解决方案。
Provides
- 定义:声明当前软件包提供了某个已存在的虚拟软件包的功能。
- 用途:用于某些类型的软件包定义多个备用虚拟名称。
Replaces
- 定义:当当前软件包要替换其他软件包的某些文件,或完全替换另一个软件包时使用。
- 用途:列出将被替换的软件包。通常与
Conflicts
一起使用,以确保被替换的软件包中的文件会被当前软件包中的文件覆盖。
这有助于开发者正确填写软件包关系项,确保软件包能在用户的系统上正常安装和运行。
依赖项填写规范
debian/control 文件是 Debian 软件包的元数据文件,包含了关于包的各种信息,包括包名、版本、维护者、依赖关系等。
所有的软件包关系都定义在在debian/control 文件中,其中Depends
字段主要负责控制软件包的依赖关系,用于声明软件包的直接依赖。
以下是一个control示例:
Source: example-package-kylin
Section: web
Priority: optional
Maintainer: Example Maintainer <maintainer@kylinos.cn>
Build-Depends: debhelper (>= 11), dh-systemd (>= 1.5)
Standards-Version: 4.1.4
Homepage: https://www.kylinos.cn/
Package: example-package-kylin
Architecture: any
Depends: libwebp6 (>= 0.6.1), libc6 (>> 2.27), python3 | python3-minimal, ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}
Description: An example package for Kylin systems
This package provides an example service with web capabilities.
It relies on several other packages to function properly, including
essential libraries and optional Python support.
Copy
Depends
字段填写指导
-
确定必需依赖包:列出在安装或运行软件包时必须存在的其他软件包。这些是绝对必要的依赖包。如果缺少其中任何一个,软件包将无法正常工作。
-
格式:
Depends
字段的格式为逗号分隔的依赖项列表。每个依赖项可以指定包名和可选的版本约束。例如:Depends: libwebp6 (>= 0.6.1), libc6 (>> 2.27)
Copy
-
版本约束:可以使用版本约束来指定依赖包的最低、最高或特定版本。常用的版本约束符号包括:
-
>=
表示大于或等于 -
<=
表示小于或等于 -
=
表示等于 -
>>
表示严格大于 -
<<
表示严格小于
-
-
逻辑运算符:可以使用逻辑运算符来指定依赖关系的选择。例如,使用竖线
|
表示逻辑“或”关系,表示多个包中的一个即可满足依赖关系:Depends: python3 | python3-minimal
Copy
-
虚拟包:如果依赖项是一个虚拟包,确保列出的包提供了该虚拟包。例如:
Depends: mail-transport-agent
Copy
注释:在麒麟系统中,虚拟包是一个抽象的包概念,它本身不直接对应任何实际的软件包,而是由一个或多个实际的软件包提供相应的功能。虚拟包用来表示一组可以互换的软件包的功能。
示例:
mail-transport-agent
-
定义:
mail-transport-agent
(MTA)是一个虚拟包,它代表了一个邮件传输代理的功能,这是用于在网络上发送和接收电子邮件的软件。 -
提供者:多个包如
exim4-daemon-light
,postfix
,sendmail
等都可以提供mail-transport-agent
虚拟包。这意味着这些软件都具备邮件传输代理的功能。 -
实现方式:安装此软件包时,麒麟系统的包管理系统会检查系统中是否已安装提供
mail-transport-agent
虚拟包的软件包。如果没有,系统会提示用户安装一个提供该虚拟包的软件包。用户可以选择安装exim4
,postfix
,sendmail
或任何其他提供此虚拟包的软件。这种方式确保软件包能够适应用户的不同选择,而不是硬编码对某个特定软件包的依赖,提高了包的通用性和灵活性。
-
-
自动依赖:当软件包依赖于某些共享库或其他资源时,这些依赖可能需要通过特殊的变量(例如:
${shlibs:Depends}
,${misc:Depends}
和${perl:Depends}
)来自动生成,以确保软件包能够正确地链接到所需的库。Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}
Copy
以上填写规范中,尤其需要注意自动依赖的填写,后续会针对自动依赖做说明
自动依赖
说明
在 银河麒麟系统软件包的构建过程中,自动依赖变量 ${shlibs:Depends}
、${perl:Depends}
和 ${misc:Depends}
的使用大大简化了依赖管理工作。这些变量在软件包的编译过程中,通过 debhelper 工具自动替换为具体的依赖包列表,确保软件包在运行时所需的所有库和组件都会被正确安装。
${shlibs:Depends}
用途:自动添加由共享库引起的依赖,主要针对依赖特定版本动态链接库的 C 和 C++ 程序。
原理:dpkg-shlibdeps
工具在构建过程中扫描当前编译的软件包所生成的可执行文件和动态库,分析它们所依赖的共享库,并根据编译环境中提供的 /var/lib/dpkg/info/*.symbols
或 *.shlibs
文件确定所需的包及其版本要求,自动将这些依赖添加到 Depends
字段。
-
共享库扫描:
dpkg-shlibdeps
工具会扫描软件包中的二进制文件,确定其所链接的共享库以及使用的符号。 -
符号文件:
/var/lib/dpkg/info/*.symbols
文件包含了共享库的符号信息,用于精确确定依赖关系。开发者应当维护好这些符号文件,以确保依赖关系的准确性。 -
版本控制:基于符号文件,
dpkg-shlibdeps
会为每个依赖库生成准确的版本需求,避免由于库版本不匹配导致的运行时错误。
${perl:Depends}
用途:自动包括 Perl 脚本或模块所需的 Perl 版本和其他模块依赖。
原理:dh_perl
工具分析 Perl 程序的用法,自动识别并添加所需的 Perl 版本和 CPAN 模块依赖。
-
Perl 版本:
dh_perl
工具能够识别所需的 Perl 版本,并将其添加到依赖列表中。 -
模块依赖:对于使用 CPAN 模块的脚本,
dh_perl
会自动添加这些模块的依赖,确保在安装包时,这些模块也会一并安装。
${misc:Depends}
用途:包含难以归类的杂项依赖。
原理:如果你的软件包需要一些特殊的工具或脚本来安装,而这些工具和脚本的依赖项不属于共享库或 Perl 模块,那么这些依赖项会被 ${misc:Depends}
自动添加。
-
杂项依赖:对于那些不属于共享库或 Perl 模块的依赖项,
misc:Depends
可以确保它们也会被正确包含。 -
举例:假设你在使用
debhelper
工具来帮助安装你的软件包,这些工具可能需要额外的一些依赖项。${misc:Depends}
会自动识别并添加这些依赖,以确保你的软件包能正确安装和运行。
扩展和实际应用
使用方法:在 debian/control
文件中,直接将 ${shlibs:Depends}
等符号添加到 Depends
字段中。
实际案例:例如,在打包一个依赖多种共享库的 C++ 程序时,手动列出所有依赖库及其版本非常繁琐且容易出错。通过使用 ${shlibs:Depends}
,打包工具会自动分析并生成正确的依赖列表,大大简化了打包过程。
自动依赖的优势:
- 简化维护:自动依赖减少了手动指定依赖的工作量,使得包维护更加简单。
- 提高准确性:自动生成的依赖关系基于实际的库和符号,能够提高依赖的准确性,避免手动错误。
- 增强兼容性:自动依赖能够确保软件包在不同的系统配置和版本上可靠运行,减少兼容性问题。
符号文件的维护:开发者在维护软件包时,确保 /var/lib/dpkg/info/*.symbols
文件的精度非常重要。这些文件记录了库的符号和版本信息,对于自动依赖的准确性至关重要。如果符号文件不准确,可能导致软件包依赖错误的库版本,进而引发运行时错误。
使用示例
假设有一个名为 mypackage
的软件包,它包含一个 C++ 程序(链接了某些共享库)和一个 Perl 脚本。debian/control
文件中的 Depends
字段可能如下:
Package: mypackage
Architecture: any
Depends: ${shlibs:Depends}, ${perl:Depends}, ${misc:Depends}
Copy
在包构建过程中,dpkg-shlibdeps
将自动解析 C++ 程序的共享库依赖,dh_perl
将解析 Perl 脚本的依赖,debhelper 工具将根据包的其他特性生成必要的依赖。最终的 Depends
字段将包含所有解析出来的依赖项。