Table of Contents
有时我们已经通过官方压缩包、SDK 管理器或其他方式,在用户目录中安装了某个运行环境,但 pacman 并不知道它的存在。
例如,我已经手动安装了 Java,并将其加入了 PATH。此时 Java 命令可以正常使用,但在安装 Minecraft 启动器时,pacman 仍可能要求安装仓库中的 Java 软件包。
这是因为 pacman 判断依赖是否满足时,主要检查的是自己的本地软件包数据库,而不是扫描 PATH,也不会检查用户目录中是否存在对应程序。
一种解决方法是创建一个只包含软件包元数据的空包,通过 PKGBUILD 中的 provides 字段,告诉 pacman:
当前系统已经通过其他方式提供了这些依赖。
例如:
pkgname=facmanpkgver=1.0.0pkgrel=1pkgdesc='Virtual package providers for pacman dependency resolution'arch=('any')license=('MIT')
provides=( 'dotnet-sdk' 'netcat' 'nodejs=26.5.0' 'npm')
package() { :}其中,provides 用来声明这个软件包能够提供哪些其他软件包或虚拟组件。安装 facman 后,当其他软件包依赖 dotnet-sdk、netcat、npm 或符合版本要求的 nodejs 时,pacman 会认为这些依赖已经得到满足。provides 正是 PKGBUILD 官方支持的虚拟依赖机制。
package() 中只有一个 :,表示不安装任何实际文件。因此,facman 本质上只是一个元数据包:它不会安装 Node.js、.NET SDK 或其他运行环境,只会将 provides 信息注册到 pacman 的本地数据库中。
将上述内容保存为 PKGBUILD 后,可以执行:
makepkg -simakepkg 会根据当前目录中的 PKGBUILD 生成 Arch 软件包,-i 会在构建完成后安装该软件包。
安装后,可以使用以下命令查看注册的虚拟依赖:
pacman -Qi facman也可以检查某个依赖是否已经得到满足:
pacman -T dotnet-sdk npm netcat 'nodejs>=18'如果没有任何输出,说明这些依赖在 pacman 看来均已满足。
关于版本
如果目标软件包只依赖包名:
depends=('npm')那么下面的声明就足够了:
provides=('npm')但如果目标软件包带有版本限制:
depends=('nodejs>=18')那么 provides 也应声明一个具体版本:
provides=('nodejs=26.5.0')provides 中应描述“当前提供的具体版本”,不能写成 nodejs>=18。依赖方会使用这个具体版本进行比较。
注意事项
这种方法只会改变 pacman 的依赖判断,不会真正提供对应的命令、动态链接库或运行环境。
因此,它适合下面这种情况:
- 已经通过官方压缩包安装了 Java 或 .NET SDK;
- 已经通过语言版本管理器安装了对应运行环境;
- 系统中确实存在与目标软件兼容的替代实现;
- 只是希望避免 pacman 再安装一份重复环境。
不建议为了减少下载量而随意伪造原生动态库依赖。假如软件运行时需要 libexample.so,仅仅添加:
provides=('example')并不会创建这个动态链接库,软件仍然可能无法启动。
另外,这个包只需要在本地通过 makepkg 构建和安装,并不一定要上传到 AUR。AUR 主要用于共享用户维护的 PKGBUILD;其中的软件仍然需要由用户使用 makepkg 构建,再通过 pacman 安装。