5.10.依赖

许多 Port 依赖于其他 Port。这是大多数类 Unix 操作系统(包括 FreeBSD)的一项非常方便的功能。多个 Port 可以共享一个共同的依赖,而不是将该依赖项与每个需要它的 Port 或包捆绑在一起。有七个变量可以用来确保所有必要的组件都在用户的机器上。此外,还有一些常见情况的预支持依赖变量,以及一些其他控制依赖行为的变量。

重要

当软件有额外的依赖项以提供额外的功能时,*_DEPENDS 中列出的基础依赖项应该包括那些对大多数用户有益的额外依赖项。基础依赖项不应是“最小”依赖集。目标不是包括所有可能的依赖项,只包括那些对大多数人有益的依赖项。

5.10.1. LIB_DEPENDS

此变量指定该 Port 依赖的共享库。它是一个 <lib:dir> 元组的列表,其中 <lib> 是共享库的名称,<dir> 是查找该库的目录,以防库不可用。例如:

LIB_DEPENDS=   libjpeg.so:graphics/jpeg

将检查是否存在共享的 jpeg 库,并且如果找不到,将深入 graphics/jpeg 子目录以构建和安装该库。

该依赖项会被检查两次,第一次在 build 目标中,第二次在 install 目标中。此外,依赖项的名称会被放入包中,以便如果用户系统中没有该库,pkg install(参见 pkg-install(8))会自动安装它。

5.10.2. RUN_DEPENDS

此变量指定该 Port 在运行时依赖的可执行文件或文件。它是一个 <path:dir>[:<target>] 元组的列表,其中 <path> 是可执行文件或文件的名称,dir 是查找它的目录,以防不可用,target 是该目录中的目标调用。如果 <path> 以斜杠(/)开头,它被视为文件,并使用 test -e 测试其是否存在;否则,它被视为可执行文件,并使用 which -s 检查程序是否存在于搜索路径中。

例如:

RUN_DEPENDS=	${LOCALBASE}/news/bin/innd:news/inn \
		xmlcatmgr:textproc/xmlcatmgr

将检查文件或目录 /usr/local/news/bin/innd 是否存在,如果不存在,它将深入 news/inn 子目录以构建和安装该文件。它还会检查 xmlcatmgr 可执行文件是否存在于搜索路径中,如果不存在,它将深入 textproc/xmlcatmgr 子目录以构建和安装该文件。

注意

在这种情况下,innd 实际上是一个可执行文件;如果可执行文件的位置不在预期的搜索路径中,可以使用完整路径。

注意

在 Ports 构建集群中使用的官方搜索 PATH

/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin

该依赖项会在 install 目标中进行检查。此外,依赖项的名称会被放入包中,以便如果用户的系统中没有该文件或程序,pkg install(参见 pkg-install(8))会自动安装它。如果 target 部分与 DEPENDS_TARGET 相同,则可以省略该部分。

一个常见的情况是,当 RUN_DEPENDSBUILD_DEPENDS 实际上是一样的,尤其是在 Ported 软件是用脚本语言编写的,或者它要求相同的构建和运行时环境时。在这种情况下,人们常常会直接将它们互相赋值:

RUN_DEPENDS=	${BUILD_DEPENDS}

然而,这种赋值可能会污染运行时依赖项,使其包含原始 BUILD_DEPENDS 中未定义的条目。这是因为 make(1) 对变量赋值的懒惰求值。考虑一个包含 USE_*Makefile,这些变量由 ports/Mk/bsd.*.mk 处理,用来增强初始构建依赖项。例如,USES= gmake 会将 devel/gmake 添加到 BUILD_DEPENDS 中。为了防止这些额外的依赖项污染 RUN_DEPENDS,可以创建另一个变量,将 BUILD_DEPENDS 的当前内容赋值给它,并将其赋给 BUILD_DEPENDSRUN_DEPENDS

MY_DEPENDS=	some:devel/some \
		other:lang/other
BUILD_DEPENDS=	${MY_DEPENDS}
RUN_DEPENDS=	${MY_DEPENDS}

重要

不要使用 :=BUILD_DEPENDS 赋值给 RUN_DEPENDS 或反之。所有变量都会立即展开,这是完全错误的做法,几乎总是会失败。

5.10.3. BUILD_DEPENDS

此变量指定该 Port 构建时所需的可执行文件或文件。与 RUN_DEPENDS 类似,它是 <path:dir>[:<target>] 元组的列表。例如:

BUILD_DEPENDS=	unzip:archivers/unzip

将检查是否存在名为 unzip 的可执行文件,如果找不到,它将深入 archivers/unzip 子目录以构建和安装该文件。

注意

这里的“build”指的是从提取到编译的整个过程。该依赖项会在 extract 目标中进行检查。如果 target 部分与 DEPENDS_TARGET 相同,则可以省略该部分。

5.10.4. FETCH_DEPENDS

此变量指定该 Port 在获取时所需的可执行文件或文件。与前两个类似,它是 <path:dir>[:<target>] 元组的列表。例如:

FETCH_DEPENDS=	ncftp2:net/ncftp2

将检查是否存在名为 ncftp2 的可执行文件,如果找不到,它将深入 net/ncftp2 子目录以构建和安装该文件。

该依赖项会在 fetch 目标中进行检查。如果 target 部分与 DEPENDS_TARGET 相同,则可以省略该部分。

5.10.5. EXTRACT_DEPENDS

此变量指定该 Port 在提取时所需的可执行文件或文件。与前面类似,它是 <path:dir>[:<target>] 元组的列表。例如:

EXTRACT_DEPENDS=	unzip:archivers/unzip

将检查是否存在名为 unzip 的可执行文件,如果找不到,它将深入 archivers/unzip 子目录以构建和安装该文件。

该依赖项会在 extract 目标中进行检查。如果 target 部分与 DEPENDS_TARGET 相同,则可以省略该部分。

注意

仅在提取操作无法正常工作时使用此变量(默认假定使用 tar)。如果提取操作无法通过 USES=tarUSES=lhaUSES=zip(参见 使用 USES)来解决,则使用此变量。

5.10.6. PATCH_DEPENDS

此变量指定该 Port 在打补丁时所需的可执行文件或文件。与前面一样,它是 <path:dir>[:<target>] 元组的列表。例如:

PATCH_DEPENDS=	${NONEXISTENT}:java/jfc:extract

将深入 java/jfc 子目录提取该文件。

该依赖项会在 patch 目标中进行检查。如果 target 部分与 DEPENDS_TARGET 相同,则可以省略该部分。

5.10.7. USES

可以通过添加参数来定义 Port 使用的不同特性和依赖项。通过在 Makefile 中添加以下行来指定:

USES= feature[:arguments]

有关完整的值列表,请参见 使用 USES

重要

USES 不能在包含 bsd.port.pre.mk 后进行赋值。

5.10.8. USE_*

有多个变量可以定义许多 Port 共享的常见依赖项。它们是可选的,但有助于减少 Port Makefile 中的冗长。每个变量以 USE_* 的形式存在。这些变量只能在 Port Makefileports/Mk/bsd.*.mk 中使用。它们不用于用户设置的选项——请使用 PORT_OPTIONS 来设置。

注意

/etc/make.conf 中设置任何 USE_*始终 不正确的。例如,设置

USE_GCC=X.Y

(其中 X.Y 是版本号)将为每个 Port(包括 lang/gccXY 本身)添加对 gccXY 的依赖!

表 8. USE_*

变量
说明

USE_GCC

该 Port 需要 GCC (gccg++) 来构建。一些 Port 需要特定的旧版本 GCC,一些 Port 需要现代的、较新的版本。通常设置为 yes(意味着始终使用来自 Port 的稳定、现代 GCC,参见 GCC_DEFAULTMk/bsd.default-versions.mk 中)。这也是默认值。也可以指定确切版本,例如 10。当基本系统的 GCC 满足请求的版本时,使用它,否则会从 Port 构建合适的编译器,并相应地调整 CCCXX。版本说明符后面的 :build 参数仅为 Port 添加构建时依赖。

例如:

USE_GCC=yes		#  Port 需要当前版本的
 GCC USE_GCC=11:build	  #  Port 仅在构建时需要 GCC 11

注意 USE_GCC=any 已被弃用,不应在新 Port 中使用

与 gmake 和 configure 相关的变量在 构建机制 中有描述,而 autoconf、automake 和 libtool 在 使用 GNU Autotools 中有描述。与 Perl 相关的变量在 使用 Perl 中有描述。X11 相关的变量列在 使用 X11 中。使用 GNOME 讨论了 GNOME,而 使用 KDE 讨论了与 KDE 相关的变量。使用 Java 记录了 Java 相关变量,而 Web 应用程序 中包含了关于 Apache、PHP 和 PEAR 模块的信息。Python 在 使用 Python 中讨论,Ruby 在 使用 Ruby 中讨论。使用 SDL 提供了用于 SDL 应用程序的变量,最后,使用 Xfce 包含了有关 Xfce 的信息。

5.10.9. 依赖项的最小版本

可以使用以下语法在任何 *_DEPENDS 中指定依赖项的最小版本,LIB_DEPENDS 除外:

p5-Spiffy>=0.26:devel/p5-Spiffy

第一个字段包含一个依赖包名称,它必须与包数据库中的条目匹配,后跟一个比较符号和一个包版本。依赖项得到满足的条件是机器上安装了 p5-Spiffy-0.26 或更高版本。

5.10.10. 依赖项说明

如上所述,调用依赖项时的默认目标是 DEPENDS_TARGET,默认为 install。这是一个用户变量;它从未在 port 的 Makefile 中定义。如果 port 需要以特殊方式处理依赖项,可以使用 *_DEPENDS:target 部分,而不是重新定义 DEPENDS_TARGET

在运行 make clean 时,port 依赖项也会自动清理。如果不希望这样,可以在环境中定义 NOCLEANDEPENDS。如果 port 的依赖列表中包含需要较长时间重建的内容,如 KDE、GNOME 或 Mozilla,这可能特别有用。

要无条件地依赖另一个 port,可以在 BUILD_DEPENDSRUN_DEPENDS 的第一个字段中使用变量 ${NONEXISTENT}。仅当需要另一个 port 的源代码时,才使用此方法。通过指定目标也可以节省编译时间。例如:

BUILD_DEPENDS=	${NONEXISTENT}:graphics/jpeg:extract

这将始终进入 jpeg port 并提取它。

5.10.11. 循环依赖是致命的

重要

不要在 Ports 树中引入任何循环依赖!

Ports 构建技术不容忍循环依赖。如果引入了循环依赖,某个地方的 FreeBSD 安装几乎会立即崩溃,接着许多人会受到影响。这些依赖很难发现。如果有疑虑,在做出更改之前,请确保运行:cd /usr/ports; make index。该过程在旧机器上可能会很慢,但它可能在过程中为很多人,包括你自己,节省不少麻烦。

5.10.12. 自动依赖引起的问题

依赖项必须显式声明或使用 OPTIONS 框架 声明。使用自动检测等其他方法会使索引变得复杂,从而导致 port 和包管理的问题。

示例 37. 错误的可选依赖声明

.include <bsd.port.pre.mk>

.if exists(${LOCALBASE}/bin/foo)
LIB_DEPENDS=	libbar.so:foo/bar
.endif

自动添加依赖的问题在于,单个 port 外的文件和设置随时可能发生变化。例如:索引已构建,然后安装了一批 ports。但其中一个 port 安装了被测试的文件。此时,索引变得不正确,因为一个已安装的 port 突然有了新的依赖项。如果其他 ports 也基于其他文件的存在来确定其依赖性,重建索引后它可能依然是错误的。

示例 38. 正确的可选依赖声明

OPTIONS_DEFINE=	BAR
BAR_DESC=	Calling cellphones via bar

BAR_LIB_DEPENDS=	libbar.so:foo/bar

测试选项变量是正确的方法。只要选项在构建索引之前已定义,就不会导致批量 ports 的索引不一致。然后可以使用简单的脚本来自动化这些 ports 及其包的构建、安装和更新。

最后更新于

这有帮助吗?