我做了很多软件测试,这需要我从源代码构建许多不同的项目。我最近从 31 升级到 Fedora 33,本质上,我遇到了一系列问题,这些问题涉及由于“缺少”依赖项而无法运行我之前构建的软件,和/或当我尝试构建软件时,我收到包或库丢失的错误,主要是在运行后./configure
,或者make
,很多时候,它们确实没有,而且肯定不是我故意删除的。其他时候,包的更新(例如 Python 3.6 -> 3.9)会导致某些脚本出现问题等......
有时它让我感到困惑(除了 python 问题)是因为,我从未真正删除过许多库,而且似乎无论出于何种原因,它们都不再被识别,所以我必须手动显示构建系统它们所在的位置,或者只是重新安装依赖项,等等......
升级 Fedora 或其他 Linux 发行版后,是否有任何一般建议可以解决这些类型的问题?我想这有点常见,虽然我能当然,我会根据具体情况解决每个单独的问题,我会考虑这是一个集体问题,并且当我继续我的 Linux 之旅时,我希望在将来升级时能够更加擅长解决这个问题。
答案1
从源代码编译任何重要的软件都可能是一项复杂的任务,尽管现在有相当多的自动化技术可以隐藏大部分细节。但是,当流程中出现问题时,您需要能够了解该流程才能有效地排除故障。
不幸的是,在我看来,对失败的编译过程进行故障排除的知识和技能越来越被理解为“只有实际的软件开发人员才拥有的东西”,而实际上它对于测试人员来说也是非常必要的,有时对于系统管理员也非常有用。事实上,开源软件的基本思想假设:每个人如果他们愿意的话,应该能够重新编译软件包。
当./configure
抱怨缺少图书馆时,通常是在真正寻找该库的 -devel 包。
./configure
实际上是一个 shell 脚本,它运行许多测试来查找和验证编译软件包的先决条件。它由工具包生成autoconf
,用于简化源代码包在多种硬件架构和类 UNIX 操作系统上可编译的工作。
有时,库开发项目或 Linux 发行版可能会对开发头文件(*.h
文件)在/usr/include/
.例如,旧版本可能将它们直接放在 下/usr/include/
,而新版本可能将它们放在/usr/include/library_name/
子目录下。如果库开发人员在源级别进行了向后不兼容的更改,则可能需要包含库版本号,以便发行版可以支持库的旧版本/usr/include/library_name/
和新版本/usr/include/library_name2
或其他内容。如果此类更改比autoconf
用于./configure
为软件包创建脚本的版本新,则它可能无法自动检测新位置。
autoconf
并不完美,还有其他机制可以补充或替代。另一个常见的情况是pkg-config
:支持它的每个库包都会在其-devel
包(或等效项)中包含一个*.pc
文件,该文件记录了重要的编译器选项、依赖项以及在构建使用相关库的软件时非常重要的其他信息。
该make
步骤通常需要实际的库包及其-devel
包都存在。当使用 构建软件包时make
,通常会将其几个部分从源代码编译为二进制文件。目标文件隔离,然后这些文件链接在一起形成可执行文件。
编译子步骤可能只需要包*.h
提供的文件-devel
,但链接子步骤要求存在实际的库包。
如果您需要为操作系统主要版本 X 编译的某些软件在操作系统主要版本 (X+n) 上运行,您可能会遇到共享库问题:
- 库发生了向后不兼容的更改
- 库已以不同方式打包以解决名称冲突或其他问题
- 旧的库已从发行版中完全删除,并且功能现在由不同的库提供,或者完全以另一种方式提供。
要解决此类问题,您可能必须找到软件实际需要的旧库,将它们放入通常不会搜索库的目录中,然后使用包装器脚本启动旧程序,该包装器脚本使用环境变量(例如LD_LIBRARY_PATH
指定库的自定义搜索路径仅适用于该应用程序。请参阅ld.so(8)
手册页,特别是其中的ENVIRONMENT
章节,了解有关更改应用程序在运行时查找共享库的方式的更多详细信息。
这样我还是可以运行Linux版本的席德·梅尔的半人马座阿尔法星(版权所有 1999)在当前的 Debian 10 系统上。我想说,不算太破旧。
答案2
升级 Fedora 或其他 Linux 发行版后,是否有任何一般建议可以解决这些类型的问题?
- 重建或
- 封装为 snap/flatpak 或
- 在 chroot 中运行或
- 在虚拟机中运行
我想这在某种程度上是常见的,虽然我当然可以根据具体情况解决每个单独的问题,但我会考虑这是一个集体问题,并且当我继续我的 Linux 之旅时,我希望变得更擅长解决当我以后升级时这个问题。
不幸的是,这就是 Linux 的本质 - 一个快速变化的目标,每次发布新的发行版本时都必须重建。这就是我经常对 Fedora 未提供的软件(例如 ffmpeg/mpv)所做的事情。