5.10.依赖

许多 Port 依赖于其他 Port 。这是包括 FreeBSD 在内的大多数类 Unix 操作系统的一个非常方便的特性。多个 port 可以共享一个共同的依赖关系, 而不是把这个依赖关系与每个需要它的 port 或软件包捆绑在一起。有七个变量可以用来确保所有需要的位子都会出现在用户的机器上。还有一些预先支持的依赖性变量用于常见的情况, 另外还有一些变量用于控制依赖性的行为。

重要

当软件有提供额外功能的依赖关系时,*_DEPENDS 中列出的基本依赖关系应该包括能使大多数用户受益的额外依赖关系。基本依赖关系不应该是一个"最小"的依赖关系集。我们的目标不是要包括所有可能的依赖关系。只包括那些能让大多数人受益的依赖。

5.10.1. LIB_DEPENDS

这个变量用于指定这个 port 所依赖的共享库。它是一个 lib:dir 元素的列表, 其中 lib 是共享库的名称, dir 是在没有共享库的情况下可以找到它的目录。举例来说,

LIB_DEPENDS=   libjpeg.so:graphics/jpeg

将检查是否有任何版本的共享 jpeg 库,如果没有找到,将进入 Ports 的 graphics/jpeg 子目录来构建和安装它。

依赖关系会被检查两次,一次是在构建目标中,另一次是在安装目标中。另外,依赖关系的名字会被放入软件包中,这样,如果用户的系统中没有这个依赖关系,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 是否存在, 如果没有找到, 则从 Ports 的 news/inn 子目录中建立并安装它。它还会查看搜索路径中是否有一个名为 xmlcatmgr 的可执行文件, 如果没有找到, 则会进入 textproc/xmlcatmgr 来构建和安装它。

注意

在这种情况下,innd 实际上是一个可执行文件;如果一个可执行文件在一个预计不会出现在搜索路径中的地方,请使用全路径名称。

注意

在 ports build cluster 上使用的官方搜索 PATH 是

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

依赖关系会在安装目标中检查。同时, 依赖关系的名字会被放入软件包中, 以便 pkg install (参见 pkg-install(8)) 能够在用户系统中没有它的时候自动安装它。如果目标部分与 DEPENDS_TARGET 相同, 则可以省略。

一个很常见的情况是, RUN_DEPENDSBUILD_DEPENDS 在字面上是一样的, 特别是当移植的软件是用脚本语言编写的, 或需要相同的构建和运行环境时。在这种情况下,将一个直接赋值给另一个既诱人又直观:

RUN_DEPENDS=	${BUILD_DEPENDS}

然而, 这样的赋值可能会污染运行时的依赖关系, 而这些依赖关系并不是在 port 的原始 BUILD_DEPENDS 中定义的条目。这是因为 make(1) 对变量赋值的懒惰评估而发生的。考虑一下带有 USE_* 的 Makefile, 它们会被 ports/Mk/bsd.*.mk 处理, 以增加初始的联编依赖关系。例如, USES= gmake 会在 BUILD_DEPENDS 中加入 devel/gmake。为了防止这种额外的依赖关系污染 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 的可执行文件, 并进入 Ports 的 archivers/unzip 子目录, 如果没有找到它, 则建立并安装它。

注意

这里的"构建"意味着从解压到编译的一切。依赖关系是在解压目标中检查的。如果目标部分与 DEPENDS_TARGET 相同,可以省略。

5.10.4. FETCH_DEPENDS

这个变量用于指定这个 port 需要获取的可执行文件或文件。和前面两个变量一样, 它是 path:dir[:target] 元组的列表。例如在,

FETCH_DEPENDS=	ncftp2:net/ncftp2

将检查是否有一个名为 ncftp2 的可执行文件, 如果没有找到, 将进入 Ports 中的 net/ncftp2 子目录来构建和安装它。

依赖关系从获取的目标中检查。如果目标部分与 DEPENDS_TARGET 相同,可以省略。

5.10.5. EXTRACT_DEPENDS

这个变量用于指定这个 port 需要解压的可执行文件或文件。和前一个变量一样, 它是 path:dir[:target] 元组的列表。例如,

EXTRACT_DEPENDS=	unzip:archivers/unzip

将检查名为 unzip 的可执行文件, 并进入 Ports 的 archivers/unzip 子目录, 如果没有找到它, 则建立并安装它。

依赖关系是在解压目标中检查的。如果目标部分与 DEPENDS_TARGET 相同,则可以省略。

注意

只有在解压工作尚未完成的情况下才使用这个变量(默认假设为 tar ),并且不能使用 USES=tarUSES=lhaUSES=zip(见使用USES宏)来使其工作。

5.10.6. PATCH_DEPENDS

这个变量用于指定这个 port 需要打补丁的可执行文件或文件。和前面的一样, 它是 path:dir[:target] 元组的列表。例如,

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

将进入 Ports 中的 java/jfc 子目录来解压它。

依赖关系是在补丁目标中检查的。如果目标部分与 DEPENDS_TARGET 相同,则可以省略。

5.10.7. USES

可以添加参数来定义 port 所使用的不同特性和依赖关系。它们可以通过在 Makefile 中加入这一行来指定:

USES= feature[:arguments]

关于完整的数值列表,请参见使用 USES 宏。

警告

在纳入 bsd.port.pre.mk 之后, 不能再分配 USES

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 添加对 gccXY 的依赖,包括 lang/gccXY 本身!

表8. USE_*

比如说:

USE_GCC=yes		# port requires a current version of GCC
USE_GCC=11:build	# port requires GCC 11 at build time only

注意

USE_GCC=any 已经过时,不应该在新的 ports 中使用。

与 gmake 和 configure 相关的变量在构建机制中描述,而 autoconf、automake 和 libtool 则在使用 GNU 自动工具中描述。与 Perl 有关的变量在 Using Perl 中描述。X11 变量在 Using X11 中列出。Using Gnome 涉及 GNOME,Using KDE 涉及 KDE 相关变量。使用 Java 记录了 Java 变量,而 Web 应用包含了关于 Apache、PHP 和PEAR 模块的信息。Python 在 Using Python 中讨论,而 Ruby 在 Using Ruby 中讨论。Using SDL 提供了用于 SDL应用程序的变量,最后,Using 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, 可以使用变量 ${NONEXISTENT} 作为 BUILD_DEPENDSRUN_DEPENDS 的第一个字段。只有在需要另一个 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 和包管理带来问题。

例41. 错误地声明了一个可选依赖关系

.include <bsd.port.pre.mk>

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

试图自动添加依赖关系的问题是, 个别 port 以外的文件和设置可能随时发生变化。例如: 建立了一个索引, 然后安装了一批 port。但其中一个 port 安装了经过测试的文件。现在索引是不正确的, 因为一个已安装的 port 意外地有了一个新的依赖关系。如果其他 port 也根据其他文件的存在来确定它们对依赖关系的需求, 则即使在重建之后, 索引仍然可能是错误的。

例42. 可选依赖关系的正确声明

OPTIONS_DEFINE=	BAR
BAR_DESC=	Calling cellphones via bar

BAR_LIB_DEPENDS=	libbar.so:foo/bar

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

最后更新于

FreeBSD 中文社区