5.17.安装文件

重要

安装阶段对最终用户来说是非常重要的, 因为它向他们的系统添加了文件。所有在 port Makefile*-install 目标中运行的额外命令, 都应该被回显到屏幕上。不要用 @.SILENT 来使这些命令沉默。

5.17.1. INSTALL_* Macros

使用 bsd.port.mk 中提供的宏来确保 port 的 *-install 目标中的文件的正确模式。直接在 pkg-plist 中用相应的条目来设置所有权, 例如 @(owner,group,)@owner owner@group group。这些操作符在被覆盖之前, 或在 pkg-plist 结束之前都是有效的, 所以记得在不再需要它们时重新设置。默认的所有权是 root:wheel。更多信息请参见基础关键词。

  • INSTALL_PROGRAM 是一个安装二进制可执行文件的命令。

  • INSTALL_SCRIPT 是一个安装可执行脚本的命令。

  • INSTALL_LIB 是一个安装共享库(但不是静态库)的命令。

  • INSTALL_KLD 是一个安装内核可加载模块的命令。有些架构不喜欢模块被剥离,所以用这个命令代替INSTALL_PROGRAM

  • INSTALL_DATA 是一个安装可共享数据的命令,包括静态库。

  • INSTALL_MAN 是一个安装手册和其他文档的命令(它不压缩任何东西)。

这些变量被设置到 install(1) 命令中,并为每种情况设置适当的标志。

重要

不要使用 INSTALL_LIB 来安装静态库,因为剥离它们会使它们变得无用。使用 INSTALL_DATA 代替。

5.17.2. 剥离二进制文件和共享库

已安装的二进制文件应该被剥离。除非绝对需要,否则不要手动剥离二进制文件。INSTALL_PROGRAM 宏在安装的同时也剥离了二进制文件。INSTALL_LIB 宏对共享库做同样的事情。

当一个文件必须被剥离, 但 INSTALL_PROGRAMINSTALL_LIB 宏都不可取时, ${STRIP_CMD} 会剥离程序或共享库。这通常是在安装后的目标中完成的。举例来说:

post-install:
	${STRIP_CMD} ${STAGEDIR}${PREFIX}/bin/xdl

当多个文件需要被剥离时:

post-install:
.for l in geometry media body track world
	${STRIP_CMD} ${STAGEDIR}${PREFIX}/lib/lib${PORTNAME}-${l}.so.0
.endfor

在一个文件上使用 file(1) 来确定它是否已经被剥离。二进制文件会被 file(1) 报告为已被剥离,或未被剥离。此外, strip(1) 会检测到已经被剥离的程序,并干净地退出。

重要

WITH_DEBUG 被定义时,elf 文件必须不被剥离。

框架提供的变量(STRIP_CMD, INSTALL_PROGRAM, INSTALL_LIB, ...)和 USES 自动处理这个问题。

有些软件,在其 LDFLAGS 中加入了 -s,在这种情况下,如果设置了 WITH_DEBUG,就删除 -s,或者无条件地删除它,在安装后使用 STRIP_CMD

5.17.3. 安装一整棵树的文件

有时,必须安装大量的文件,同时保留它们的层次结构。例如, 将整个目录树从 WRKSRC 复制到 PREFIX 下的目标目录。请注意 PREFIXEXAMPLESDIRDATADIR 和其他路径变量必须始终以 STAGEDIR 为前缀, 以尊重分期付款 (参见分期付款)。

有两个宏用于这种情况。使用这些宏而不是 cp 的好处是, 它们可以保证目标文件的正确所有权和权限。第一个宏, COPYTREE_BIN, 将把所有安装的文件设置为可执行文件, 因此适合安装到 PREFIX/bin。第二个宏,COPYTREE_SHARE,不设置文件的可执行权限,因此适合于在 PREFIX/share 目标下安装文件。

post-install:
	${MKDIR} ${STAGEDIR}${EXAMPLESDIR}
	(cd ${WRKSRC}/examples && ${COPYTREE_SHARE} . ${STAGEDIR}${EXAMPLESDIR})

这个例子将把供应商 distfile 中的 examples 目录的内容安装到 port 中适当的 examples 位置。

post-install:
	${MKDIR} ${STAGEDIR}${DATADIR}/summer
	(cd ${WRKSRC}/temperatures && ${COPYTREE_SHARE} "June July August" ${STAGEDIR}${DATADIR}/summer)

而这个例子将把夏季各月的数据安装到一个 DATADIR 的夏季子目录下。

额外的查找参数可以通过第三个参数传递给 COPYTREE_* 宏。例如,要安装第一个例子中除 Makefiles 之外的所有文件,可以使用这些命令。

post-install:
	${MKDIR} ${STAGEDIR}${EXAMPLESDIR}
	(cd ${WRKSRC}/examples && \
	${COPYTREE_SHARE} . ${STAGEDIR}${EXAMPLESDIR} "! -name Makefile")

这些宏不会将已安装的文件添加到 pkg-plist 中。它们必须手动添加。对于可选的文档 (PORTDOCS, 参见 安装附加文档) 和示例 (PORTEXAMPLES), 必须在 pkg-plist 中预留 %%PORTDOCS%%%%PORTEXAMPLES%% 前缀。

5.17.4. 安装附加文件

如果该软件除了标准的 man 和 info 页之外还有一些对用户有用的文档,请将其安装在 DOCSDIR 下。这可以像前一项一样,在安装后的目标中完成。

为 port 创建一个新的目录。这个目录的名字是 DOCSDIR。这通常等同于 PORTNAME。不过, 如果用户可能希望同时安装不同版本的 port, 可以使用整个 PKGNAME

由于只有 pkg-plist 中列出的文件才会被安装,因此安全的做法是始终将文件安装到 STAGEDIR (参见 Staging)。因此,只有当所安装的文件大到足以造成明显的 I/O 开销时,才需要 .if 块。

post-install:
	${MKDIR} ${STAGEDIR}${DOCSDIR}
	${INSTALL_DATA} ${WRKSRC}/docs/xvdocs.ps ${STAGEDIR}${DOCSDIR}

另一方面, 如果 port 中有 DOCS 选项, 则应在 post-install-DOCS-on 目标中安装文档。这些目标在 Additional Build Targetstarget-OPT-ontarget-OPT-off 中有所描述。

下面是一些方便的变量,以及它们在 Makefile 中使用时的默认扩展方式:

  • DATADIR 被扩展为PREFIX/share/PORTNAME

  • DATADIR_REL 被扩展为share/PORTNAME

  • DOCSDIR 被扩展为PREFIX/share/doc/PORTNAME

  • DOCSDIR_REL 被扩展为share/doc/PORTNAME

  • EXAMPLESDIR 被扩展为PREFIX/share/examples/PORTNAME

  • EXAMPLESDIR_REL 被扩展为share/examples/PORTNAME

注意

DOCS 选项只控制安装在 DOCSDIR 中的额外文档。它并不适用于标准的 man 页和 info 页。安装在 EXAMPLESDIR 的东西由 EXAMPLES 选项控制。

这些变量会被输出到 PLIST_SUB。如果可能的话, 它们的值将以相对于 PREFIX 的路径名出现在那里。也就是说, 在装箱单中, share/doc/PORTNAME 将被默认替换为 %%DOCSDIR%%, 以此类推。(关于 pkg-plist 替换的更多信息,请参见[这里](https://docs.freebsd.org/en/books/porters-handbook/book/#plist-sub)。

所有有条件安装的文档文件和目录都包括在 pkg-plist 中, 其前缀为 %%PORTDOCS%%, 例如:

%%PORTDOCS%%%%DOCSDIR%%/AUTHORS
%%PORTDOCS%%%%DOCSDIR%%/CONTACT

作为在 pkg-plist 中列举文档文件的一种替代方法, port 可以将 PORTDOCS 变量设置为文件名和 shell glob 模式的列表, 以加入到最终的打包列表中。这些名字将是相对于 DOCSDIR 的。因此, 利用 PORTDOCS 的 port, 如果使用了非默认的文档位置, 就必须相应地设置 DOCSDIR。如果一个目录被列在 PORTDOCS 中, 或被这个变量的 glob 模式所匹配, 那么整个包含文件和目录的子树将被登记在最终的装箱单中。如果没有设置 DOCS 选项, 则 PORTDOCS 中列出的文件和目录将不会被安装或添加到 port 包装列表中。如上所示, 在 PORTDOCS 中安装文档的工作仍由 port 自己决定。一个利用 PORTDOCS 的典型例子:

PORTDOCS=	README.* ChangeLog docs/*

注意

对于安装在 DATADIREXAMPLESDIR 下的文件, PORTDOCS 的对应物分别是 PORTDATAPORTEXAMPLES

pkg-message 的内容会在安装时显示。详情请参见使用 pkg-message 一节pkg-message 不需要被添加到 pkg-plist 中。

5.17.5. PREFIX 下的子目录

试着让 port 把东西放到 PREFIX 的正确子目录里。有些 port 会把所有东西混在一起, 放在以 port 的名字命名的子目录中, 这是不正确的。另外, 许多 port 把除了二进制文件、 头文件和手册页之外的所有东西都放在 lib 的子目录中, 这与 BSD 的范式不相符。许多文件必须移到这些目录中: etc (设置/配置文件)、 libexec (内部启动的可执行文件)、 sbin (供超级用户/管理员使用的可执行文件)、 info (信息浏览器的文档) 或 share (与架构无关的文件)。详情请参见 hier(7); 管理 /usr 的规则也几乎适用于 /usr/local。例外的情况是处理 USENET “新闻”的 port。它们可以使用 PREFIX/news 作为其文件的目的地。

最后更新于

FreeBSD 中文社区