第 5 章. 配置 Makefile

配置 Makefile 非常简单,我们建议在开始之前查看现有的示例。此外,本手册中有一个 Makefile 示例,请查看并按照该模板中变量和部分的顺序进行操作,以便使其他人更容易阅读该端口。

在设计新的 Makefile 时,请按顺序考虑以下问题:

5.1. 原始源代码

它是否以标准的 gzip 压缩的 tarball 形式存放在 DISTDIR 中,其名称类似于 foozolix-1.2.tar.gz?如果是,请继续下一步。如果不是,则分发文件格式可能需要覆盖一个或多个 DISTVERSIONDISTNAMEEXTRACT_CMDEXTRACT_BEFORE_ARGSEXTRACT_AFTER_ARGSEXTRACT_SUFXDISTFILES

在最坏的情况下,创建一个自定义的 do-extract 目标来覆盖默认目标。这种情况很少发生,甚至几乎从不发生。

5.2. 命名

端口的 Makefile 的第一部分命名端口,描述其版本号,并将其列在正确的类别中。

5.2.1. PORTNAME

PORTNAME 设置为软件的基本名称。它用作 FreeBSD 包和 DISTNAME 的基础。

包名称在整个端口树中必须是唯一的。确保 PORTNAME 未被现有端口使用,并且没有其他端口具有相同的 PKGBASE。如果名称已被使用,则添加 PKGNAMEPREFIXPKGNAMESUFFIX

5.2.2. 版本,DISTVERSION PORTVERSION

DISTVERSION 设置为软件的版本号。

PORTVERSION 是 FreeBSD 软件包使用的版本。它将自动从 DISTVERSION 推导出来,以兼容 FreeBSD 的软件包版本控制方案。如果版本包含字母,则可能需要设置 PORTVERSION 而不是 DISTVERSION

一次只能设置 PORTVERSIONDISTVERSION 中的一个。

有时,某些软件会使用与 DISTVERSIONPORTVERSION 中的转换方式不兼容的版本方案。

更新端口时,可以使用 pkg-version(8)-t 参数来检查新版本是大于还是小于之前的版本。请参阅 使用 pkg-version\(8] 比较版本)

示例 1. 使用 pkg-version(8) 比较版本

pkg version -t 以两个版本作为参数,如果第一个版本分别小于、等于或大于第二个版本,它将返回 <=>

% pkg version -t 1.2 1.3
< (1)
% pkg version -t 1.2 1.2
= (2)
% pkg version -t 1.2 1.2.0
= (3)
% pkg version -t 1.2 1.2.p1
> (4)
% pkg version -t 1.2.a1 1.2.b1
< (5)
% pkg version -t 1.2 1.2p1
< (6)
11.21.3 之前。
21.21.2 相等,因为它们具有相同的版本。
31.21.2.0 相等,因为任何东西都等于零。
41.21.2.p1 之后,因为 .p1,可以理解为“预发布版 1”。
51.2.a11.2.b1 之前,可以理解为“alpha”和“beta”,并且 ab 之前。
61.21.2p1 之前,因为 2p1,可以理解为“2,补丁级别 1”,这是一个在任何 2.X 之后但 3 之前的版本。

在这里,abp 的使用方式就像分别表示“alpha”、“beta”或“预发布版”和“补丁级别”,但它们只是字母,按字母顺序排序,因此可以使用任何字母,并且它们将被适当地排序。

表 1. DISTVERSION 和派生的 PORTVERSION 示例
DISTVERSIONPORTVERSION

0.7.1d

0.7.1.d

10Alpha3

10.a3

3Beta7-pre2

3.b7.p2

8:f_17

8f.17

示例 2. 使用 DISTVERSION

当版本仅包含由点、破折号或下划线分隔的数字时,使用 DISTVERSION

PORTNAME=   nekoto
DISTVERSION=	1.2-4

它将生成 1.2.4PORTVERSION

示例 3. 版本以字母或前缀开头时使用 DISTVERSION

当版本以字母开头或结尾,或包含版本之外的前缀或后缀时,使用 DISTVERSIONPREFIXDISTVERSIONDISTVERSIONSUFFIX

如果版本为 v1.2-4

PORTNAME=   nekoto
DISTVERSIONPREFIX=  v
DISTVERSION=	1_2_4

有时,使用 GitHub 的项目会在其版本中使用其名称。例如,版本可能是 nekoto-1.2-4

PORTNAME=   nekoto
DISTVERSIONPREFIX=  nekoto-
DISTVERSION=	1.2_4

这些项目有时还会在版本末尾使用一些字符串,例如 1.2-4_RELEASE

PORTNAME=   nekoto
DISTVERSION=	1.2-4
DISTVERSIONSUFFIX=  _RELEASE

或者它们同时使用两者,例如 nekoto-1.2-4_RELEASE

PORTNAME=   nekoto
DISTVERSIONPREFIX=  nekoto-
DISTVERSION=	1.2-4
DISTVERSIONSUFFIX=  _RELEASE

构造 PORTVERSION 时不会使用 DISTVERSIONPREFIXDISTVERSIONSUFFIX,但仅在 DISTNAME 中使用。

所有这些都将生成 1.2.4PORTVERSION

示例 4. 版本包含表示“alpha”、“beta”或“预发布版”的字母时使用 DISTVERSION

当版本包含由点、破折号或下划线分隔的数字,并且字母用于表示“alpha”、“beta”或“预发布版”(即在没有字母的版本之前)时,使用 DISTVERSION

PORTNAME=   nekoto
DISTVERSION=	1.2-pre4
PORTNAME=   nekoto
DISTVERSION=	1.2p4

两者都将生成 1.2.p4PORTVERSION,它在 1.2 之前。可以使用 pkg-version(8) 检查这一事实。

% pkg version -t 1.2.p4 1.2
<
示例 5. 版本包含表示“补丁级别”的字母时不使用 DISTVERSION

当版本包含的字母不表示“alpha”、“beta”或“pre”,而是更多地表示“补丁级别”,并且表示在没有字母的版本之后时,使用 PORTVERSION

PORTNAME=   nekoto
PORTVERSION=	1.2p4

在这种情况下,无法使用 DISTVERSION,因为它将生成 1.2.p4 的版本,这将位于 1.2 之前而不是之后。 pkg-version(8) 将验证这一点。

% pkg version -t 1.2 1.2.p4
> (1)
% pkg version -t 1.2 1.2p4
< (2)
11.21.2.p4 之后,在这种情况下是错误的
21.21.2p4 之前,这是需要的。

有关设置 PORTVERSION 的更多高级示例(当软件的版本控制与 FreeBSD 的版本控制确实不兼容时)或 DISTNAME(当发行版文件本身不包含版本时),请参阅 DISTNAME

5.2.3. PORTREVISIONPORTEPOCH

5.2.3.1. PORTREVISION

PORTREVISION 是一个单调递增的值,每次 DISTVERSION 增加(通常是在每次发布新的官方供应商版本时)都会重置为 0。如果 PORTREVISION 非零,则该值将附加到包名中。PORTREVISION 的更改由 pkg-version(8) 等自动化工具用于确定是否有新的软件包可用。

每次对端口进行更改以任何方式更改生成的软件包时,都必须增加 PORTREVISION。这包括仅影响使用非默认 选项 构建的软件包的更改。

必须增加 PORTREVISION 的示例

  • 添加修补程序以更正安全漏洞、错误或向端口添加新功能。

  • 更改端口 Makefile 以启用或禁用软件包中的编译时选项。

  • 更改打包列表或软件包的安装时行为。例如,更改生成软件包初始数据的脚本,例如 ssh(1) 主机密钥。

  • 端口的共享库依赖项的版本升级(在这种情况下,尝试在安装了较新版本的依赖项后安装旧软件包的人员将失败,因为它将查找旧的 libfoo.x 而不是 libfoo.(x+1))。

  • 对端口 distfile 的静默更改,这些更改具有重大的功能差异。例如,对 distfile 的更改需要对 distinfo 进行更正,而没有相应的 DISTVERSION 更改,其中旧版本和新版本的 diff -ru 显示代码的非平凡更改。

  • 更改 MAINTAINER

不需要增加 PORTREVISION 的更改示例

  • 对端口框架的样式更改,对最终软件包中显示的内容没有功能性更改。

  • MASTER_SITES 或对端口的其他功能更改,这些更改不会影响最终软件包。

  • 对 distfile 的微不足道的修补程序,例如更正错别字,这些错误不重要,以至于软件包的用户不必费心升级。

  • 构建修复,导致以前无法编译的软件包变得可编译。只要更改不会在端口以前可以构建的任何其他平台上引入任何功能更改。由于 PORTREVISION 反映软件包的内容,如果软件包以前无法构建,则无需增加 PORTREVISION 以标记更改。

经验法则是确定提交到端口的更改是否会让某些人受益。无论是由于增强、修复还是由于新软件包实际上可以正常工作。然后权衡这一事实,即它将导致所有定期更新其端口树的人员被迫更新。如果是,则必须增加 PORTREVISION

如果 PORTREVISION 没有增加,使用二进制软件包的人员将永远看不到更新。如果不增加 PORTREVISION,软件包构建器将无法检测到更改,因此不会重建软件包。

5.2.3.2. PORTEPOCH

有时,软件供应商或 FreeBSD 维护人员会做一些愚蠢的事情,并发布其软件的版本,该版本实际上在数值上小于先前版本。例如,一个端口从 foo-20000801 变为 foo-1.0(前者将被错误地视为较新版本,因为 20000801 在数值上大于 1)。

版本号比较的结果并不总是显而易见的。可以使用 pkg version(请参阅 pkg-version(8))来测试两个版本号字符串的比较。例如

% pkg version -t 0.031 0.29
>

> 输出表明版本 0.031 被认为大于版本 0.29,这可能对维护人员来说并不明显。

在这种情况下,必须增加 PORTEPOCH。如果 PORTEPOCH 非零,它将附加到软件包名称中,如上文第 0 节所述。PORTEPOCH 绝不能减少或重置为零,因为这会导致与早期纪元的软件包的比较失败。例如,软件包不会被检测为已过期。上述示例中的新版本号 1.0,1 仍然在数值上小于先前版本 20000801,但 ,1 后缀由自动化工具特殊处理,并发现它大于早期软件包上的隐式后缀 ,0

错误地删除或重置 PORTEPOCH 会导致无尽的麻烦。如果上述讨论不够清楚,请咨询 FreeBSD 端口邮件列表

预计大多数端口不会使用 PORTEPOCH,并且明智地使用 DISTVERSION 或仔细使用 PORTVERSION 通常可以防止在软件的未来版本更改版本结构时变得必要。但是,当供应商发布没有官方版本号的版本(例如代码“快照”版本)时,FreeBSD 维护人员需要注意。诱惑是使用发布日期标记版本,这将在发布新的“正式”版本时导致如上例所示的问题。

例如,如果在 20000917 日期发布了快照版本,并且软件的先前版本是 1.2 版本,请勿将 20000917 用于 DISTVERSION。正确的方法是将 DISTVERSION 设置为 1.2.20000917 或类似值,以便后续版本(例如 1.3)仍然是数值上更大的值。

5.2.3.3. PORTREVISIONPORTEPOCH 用法示例

gtkmumble 端口,版本 0.10,已提交到端口集合

PORTNAME=	gtkmumble
DISTVERSION=	0.10

PKGNAME 变为 gtkmumble-0.10

发现了安全漏洞,需要本地 FreeBSD 修补程序。相应地增加了 PORTREVISION

PORTNAME=	gtkmumble
DISTVERSION=	0.10
PORTREVISION=	1

PKGNAME 变为 gtkmumble-0.10_1

供应商发布了一个新版本,版本号为0.2(事实证明,作者实际上希望0.10表示0.1.0,而不是“0.9之后的版本”——哎呀,现在太晚了)。由于新的次要版本2在数值上小于之前的版本10,因此必须增加PORTEPOCH以手动强制检测新软件包为“较新”。由于这是代码的新供应商版本,因此PORTREVISION重置为0(或从Makefile中删除)。

PORTNAME=	gtkmumble
DISTVERSION=	0.2
PORTEPOCH=	1

PKGNAME变为gtkmumble-0.2,1

下一个版本是0.3。由于PORTEPOCH永远不会减少,因此版本变量现在为

PORTNAME=	gtkmumble
DISTVERSION=	0.3
PORTEPOCH=	1

PKGNAME变为gtkmumble-0.3,1

如果在此升级过程中将PORTEPOCH重置为0,则安装了gtkmumble-0.10_1软件包的用户将不会检测到gtkmumble-0.3软件包为较新版本,因为3在数值上仍然小于10。请记住,这正是PORTEPOCH存在的全部意义所在。

5.2.4. PKGNAMEPREFIXPKGNAMESUFFIX

两个可选变量PKGNAMEPREFIXPKGNAMESUFFIXPORTNAMEPORTVERSION组合形成PKGNAME,格式为${PKGNAMEPREFIX}${PORTNAME}${PKGNAMESUFFIX}-${PORTVERSION}。确保这符合我们关于良好软件包名称的指南。特别是,在PORTVERSION中使用连字符(-)是**不允许**的。此外,如果软件包名称包含language--compiled.specifics部分(见下文),请分别使用PKGNAMEPREFIXPKGNAMESUFFIX。不要将它们作为PORTNAME的一部分。

5.2.5. 软件包命名约定

以下是命名软件包时应遵循的约定。这样做是为了使软件包目录易于扫描,因为已经存在数千个软件包,如果用户感到眼睛疲劳,他们会离开!

软件包名称采用language_region-name-compiled.specifics-version.numbers的形式。

软件包名称定义为${PKGNAMEPREFIX}${PORTNAME}${PKGNAMESUFFIX}-${PORTVERSION}。确保设置变量以符合该格式。

language_region-

FreeBSD 努力支持其用户的母语。当端口特定于某种语言时,language-部分是根据 ISO-639 定义的自然语言的两位字母缩写。例如,ja表示日语,ru表示俄语,vi表示越南语,zh表示中文,ko表示韩语,de表示德语。

如果端口特定于语言区域内的某个特定区域,则也添加两位字母的国家代码。例如,en_US表示美国英语,fr_CH表示瑞士法语。

language-部分在PKGNAMEPREFIX中设置。

name

确保端口的名称和版本清晰地分开,并放置在PORTNAMEDISTVERSION中。PORTNAME包含版本部分的唯一原因是上游发行版确实以这种方式命名,例如textproc/libxml2japanese/kinput2-freewnn端口。否则,PORTNAME不能包含任何版本特定的信息。多个端口具有相同的PORTNAME是很正常的,就像www/apache*端口一样;在这种情况下,不同的版本(和不同的索引条目)由PKGNAMEPREFIXPKGNAMESUFFIX的值区分。

有一种传统是通过在前面添加p5-并将双冒号分隔符转换为连字符来命名Perl 5模块。例如,Data::Dumper模块变为p5-Data-Dumper

-compiled.specifics

如果端口可以使用不同的硬编码默认值(通常是端口系列中目录名称的一部分)进行构建,则-compiled.specifics部分声明编译时默认值。连字符是可选的。例如,纸张尺寸和字体单位。

-compiled.specifics部分在PKGNAMESUFFIX中设置。

-version.numbers

版本字符串紧跟一个连字符(-),并且是一个用点分隔的整数和单个小写字母列表。特别是,不允许在版本字符串内部使用另一个连字符。唯一的例外是字符串pl(表示“补丁级别”),它**仅**在软件中没有主要版本号和次要版本号时才能使用。如果软件版本包含“alpha”、“beta”、“rc”或“pre”等字符串,请取第一个字母并将其立即放在点之后。如果版本字符串在这些名称之后继续,则数字在单个字母之后跟随,它们之间没有额外的点(例如,1.0b2)。

这样做是为了通过查看版本字符串更容易对端口进行排序。特别是,确保版本号组件始终用点分隔,如果日期是字符串的一部分,请使用dyyyy.mm.dd格式,而不是dd.mm.yyyy或不兼容 Y2K 的yy.mm.dd格式。重要的是在版本前面加上一个字母,这里为d(表示日期),以防发布具有实际版本号的版本,该版本在数值上将小于yyyy

软件包名称在整个端口树中必须是唯一的,请检查是否已存在具有相同PORTNAME的端口,如果存在,请添加PKGNAMEPREFIXPKGNAMESUFFIX之一。

以下是一些(真实的)示例,说明如何将软件作者调用的名称转换为合适的软件包名称,对于每一行,仅在DISTVERSIONPORTVERSION中设置一个,具体取决于哪个将在端口的Makefile中使用

表 2. 软件包命名示例
发行版名称PKGNAMEPREFIXPORTNAMEPKGNAMESUFFIXDISTVERSIONPORTVERSION原因或注释

mule-2.2.2

(空)

mule

(空)

2.2.2

无需更改

mule-1.0.1

(空)

mule

1

1.0.1

这是 mule 的版本 1,并且版本 2 已经存在

EmiClock-1.0.2

(空)

emiclock

(空)

1.0.2

单个程序的名称不使用大写字母

rdist-1.3alpha

(空)

rdist

(空)

1.3alpha

版本将为1.3.a

es-0.9-beta1

(空)

es

(空)

0.9-beta1

版本将为0.9.b1

mailman-2.0rc3

(空)

mailman

(空)

2.0rc3

版本将为2.0.r3

v3.3beta021.src

(空)

tiff

(空)

3.3

这到底是什么?

tvtwm

(空)

tvtwm

(空)

p11

文件名中没有版本,使用上游所说的版本

piewm

(空)

piewm

(空)

1.0

文件名中没有版本,使用上游所说的版本

xvgr-2.10pl1

(空)

xvgr

(空)

2.10.pl1

在这种情况下,pl1表示补丁级别,因此无法使用DISTVERSION。

gawk-2.15.6

ja-

gawk

(空)

2.15.6

日语版本

psutils-1.13

(空)

psutils

-letter

1.13

在软件包构建时硬编码纸张尺寸

pkfonts

(空)

pkfonts

300

1.0

300dpi 字体的软件包

如果原始源代码中绝对没有版本信息的痕迹,并且原始作者不太可能发布另一个版本,只需将版本字符串设置为1.0(如上面的piewm示例)。否则,请询问原始作者或使用源文件发布的日期字符串(dyyyy.mm.dddyyyymmdd)作为版本。

使用任何字母。这里,d表示日期,如果源代码是 Git 存储库,则通常使用g后跟提交日期,使用s表示快照也很常见。

5.3. 分类

5.3.1. CATEGORIES

创建软件包时,它会被放在/usr/ports/packages/All下,并从/usr/ports/packages的一个或多个子目录创建链接。这些子目录的名称由变量CATEGORIES指定。其目的是在用户浏览 FTP 站点或 CDROM 上的大量软件包时,使他们的生活更轻松。请查看当前类别列表,并选择适合该端口的类别。

此列表还确定端口在端口树中的导入位置。如果这里有多个类别,则端口文件必须放在第一个类别的名称的子目录中。有关如何选择正确类别的更多讨论,请参见下文

5.3.2. 当前类别列表

以下是端口类别的当前列表。标有星号(*)的类别是虚拟类别——那些在端口树中没有相应子目录的类别。它们仅用作辅助类别,仅用于搜索目的。

对于非虚拟类别,该子目录的Makefile中的COMMENT中有一行描述。

类别描述备注

accessibility

帮助残疾用户的端口。

afterstep*

支持AfterStep窗口管理器的端口。

arabic

阿拉伯语支持。

archivers

归档工具。

astro

天文端口。

audio

声音支持。

benchmarks

基准测试实用程序。

biology

与生物学相关的软件。

cad

计算机辅助设计工具。

chinese

中文支持。

comms

通信软件。

主要是与串行端口通信的软件。

converters

字符代码转换器。

databases

数据库。

deskutils

在计算机发明之前就存在于桌面上的东西。

devel

开发工具。

不要仅仅因为它们是库就将库放在这里。除非它们确实不属于其他任何地方,否则它们**不应**在此类别中。

dns

与 DNS 相关的软件。

docs*

FreeBSD 文档的元端口。

editors

通用编辑器。

专用编辑器位于这些工具的部分。例如,数学公式编辑器将位于math中,并具有editors作为第二个类别。

education*

教育相关的软件。

这包括主要或实质上旨在帮助用户学习特定主题或进行一般学习的应用程序、实用程序或游戏。它还包括课程编写应用程序、课程交付应用程序以及课堂或学校管理应用程序。

elisp*

Emacs Lisp 移植。

emulators

其他操作系统的模拟器。

终端模拟器**不**属于这里。基于 X 的模拟器属于 x11,基于文本的模拟器则根据具体功能属于 commsmisc

enlightenment*

与 Enlightenment 窗口管理器相关的移植。

finance

货币、金融及相关应用程序。

french

法语支持。

ftp

FTP 客户端和服务器实用程序。

如果端口同时支持 FTP 和 HTTP,则将其放在 ftp 中,并将其作为 www 的二级类别。

games

游戏。

geography*

地理相关的软件。

german

德语支持。

gnome*

来自 GNOME 项目的移植。

gnustep*

与 GNUstep 桌面环境相关的软件。

graphics

图形实用程序。

hamradio*

业余无线电软件。

haskell*

与 Haskell 语言相关的软件。

hebrew

希伯来语支持。

hungarian

匈牙利语支持。

irc

Internet Relay Chat 实用程序。

japanese

日语支持。

java

与 Java™ 语言相关的软件。

java 类别不能是端口的唯一类别。除了与 Java 语言直接相关的端口外,还鼓励移植者不要将 java 作为端口的主要类别。

kde*

来自 KDE 项目(通用)的移植。

kde-applications*

来自 KDE 项目的应用程序。

kde-frameworks*

来自 KDE 项目的附加库,用于使用 Qt 进行编程。

kde-plasma*

来自 KDE 项目的桌面。

kld*

内核可加载模块。

korean

韩语支持。

lang

编程语言。

linux*

Linux 应用程序和支持实用程序。

lisp*

与 Lisp 语言相关的软件。

mail

邮件软件。

mate*

与 MATE 桌面环境相关的移植,它是 GNOME 2 的分支。

math

数值计算软件和其他数学实用程序。

mbone*

MBone 应用程序。

misc

其他实用程序

不属于其他任何类别的东西。如果可能,请尝试为端口找到比misc更好的类别,因为端口往往会被忽略在这里。

multimedia

多媒体软件。

net

其他网络软件。

net-im

即时通讯软件。

net-mgmt

网络管理软件。

net-p2p

对等网络应用程序。

net-vpn*

虚拟专用网络应用程序。

news

USENET 新闻软件。

parallel*

处理计算并行性的应用程序。

pear*

与 Pear PHP 框架相关的移植。

perl5*

需要 Perl 5 版本才能运行的移植。

plan9*

来自 Plan9 的各种程序。

polish

波兰语支持。

ports-mgmt

用于管理、安装和开发 FreeBSD 端口和软件包的端口。

portuguese

葡萄牙语支持。

print

打印软件。

桌面出版工具(预览器等)也属于这里。

python*

Python 语言相关的软件。

ruby*

Ruby 语言相关的软件。

rubygems*

RubyGems 包的移植。

russian

俄语支持。

scheme*

与 Scheme 语言相关的软件。

science

不适合其他类别(如 astrobiologymath)的科学端口。

security

安全实用程序。

shells

命令行 shell。

spanish*

西班牙语支持。

sysutils

系统实用程序。

tcl*

使用 Tcl 运行的端口。

textproc

文本处理实用程序。

它不包括桌面出版工具,这些工具属于 print

tk*

使用 Tk 运行的端口。

ukrainian

乌克兰语支持。

vietnamese

越南语支持。

wayland*

支持 Wayland 显示服务器的端口。

windowmaker*

支持 Window Maker 窗口管理器的端口。

www

与万维网相关的软件。

HTML 语言支持也属于这里。

x11

X 窗口系统及其相关工具。

此类别仅适用于直接支持窗口系统的软件。不要将常规的 X 应用程序放在这里。大多数都属于其他 x11-* 类别(见下文)。

x11-clocks

X11 时钟。

x11-drivers

X11 驱动程序。

x11-fm

X11 文件管理器。

x11-fonts

X11 字体和字体实用程序。

x11-servers

X11 服务器。

x11-themes

X11 主题。

x11-toolkits

X11 工具包。

x11-wm

X11 窗口管理器。

xfce*

Xfce 桌面环境相关的移植。

zope*

Zope 支持。

5.3.3. 选择正确的类别

由于许多类别存在重叠,因此选择哪个类别将成为端口的主要类别可能会很繁琐。有一些规则来管理这个问题。以下是优先级列表,按优先级递减顺序排列

  • 第一个类别必须是物理类别(见 上文)。这是为了使打包工作正常进行。之后可以混合使用虚拟类别和物理类别。

  • 特定语言的类别始终放在首位。例如,如果端口安装了日语 X11 字体,则CATEGORIES行将读取 japanese x11-fonts

  • 特定类别列在不太具体的类别之前。例如,HTML 编辑器列为 www editors,而不是反过来。此外,当端口属于 ircmailnewssecuritywww 中的任何一个时,不要列出 net,因为 net 是隐含包含的。

  • x11 仅在主要类别为自然语言时才用作辅助类别。特别是,不要在 X 应用程序的类别行中放入 x11

  • Emacs 模式与模式支持的应用程序放在同一个端口类别中,而不是放在 editors 中。例如,用于编辑某种编程语言源文件的 Emacs 模式属于 lang

  • 安装可加载内核模块的端口在其CATEGORIES行中也具有虚拟类别 kld。这是通过添加USES=kmod自动处理的事情之一。

  • misc 不与任何其他非虚拟类别一起出现。如果CATEGORIES中存在misc与其他内容,则意味着可以安全地删除misc,并将端口仅放置在其他子目录中。

  • 如果端口确实不属于其他任何类别,则将其放在 misc 中。

如果类别不明确,请在错误数据库中的 端口提交 中添加注释说明情况,以便在导入之前进行讨论。作为提交者,请向 FreeBSD 端口邮件列表 发送通知,以便我们首先进行讨论。很多时候,新端口被导入到错误的类别,然后立即被移动。

5.3.4. 提出新的类别

随着 Ports Collection 的发展,引入了各种新的类别。新类别可以是虚拟类别——那些在端口树中没有相应子目录的类别——或物理类别——那些有相应子目录的类别。本节讨论创建新物理类别所涉及的问题。在提出新类别之前,请仔细阅读本节内容。

我们现有的做法是避免创建新的物理类别,除非大量端口在逻辑上属于该类别,或者属于该类别的端口是一个逻辑上不同的组,并且对普通用户来说兴趣有限(例如,与人类语言相关的类别),或者最好两者兼而有之。

这样做的理由是,这样的更改会给提交者和所有跟踪 Ports Collection 更改的用户带来相当大的工作量。此外,提出的类别更改似乎自然会引起争议。(也许这是因为关于何时类别“太大”、类别是否应该适合浏览(以及多少类别才是理想数量)等方面没有明确的共识。)

以下是流程

  1. FreeBSD 端口邮件列表 上提出新类别。包括新类别的详细理由,包括为什么现有的类别不足,以及提议移动的现有端口列表。(如果有新的端口在 Bugzilla 中待处理,并且适合此类别,也请列出它们。)如果你是维护者和/或提交者,请分别说明这一点,因为这可能有助于你的提案。

  2. 参与讨论。

  3. 如果看起来大家支持这个想法,请提交一个 PR,其中包含理由以及需要移动的现有端口列表。理想情况下,此 PR 还应包含以下补丁

    • 新端口在 repocopy 之后生成的 Makefile

    • 新类别的 Makefile

    • 旧端口类别对应的 Makefile

    • 依赖于旧端口的端口对应的 Makefile

    • (额外奖励:根据提交者指南中的流程,包含其他需要更改的文件。)

  4. 由于这会影响端口基础设施,并且涉及移动和修补许多端口,以及可能在构建集群上运行回归测试,因此请将 PR 指派给端口管理团队 <[email protected]>。

  5. 如果该 PR 获得批准,则提交者需要按照 提交者指南中概述的其余流程进行操作。

提出新的虚拟类别类似于上述操作,但涉及的方面要少得多,因为实际上不需要移动任何端口。在这种情况下,PR 中唯一需要包含的补丁是将新类别添加到受影响端口的 CATEGORIES 中的补丁。

5.3.5. 提出重新组织所有类别

偶尔有人会提出使用双层结构或其他某种关键词结构来重新组织类别。迄今为止,这些提议都没有结果,因为尽管它们很容易提出,但要对整个现有的端口集合进行任何形式的重组所付出的努力至少可以说是令人望而却步的。在发布此想法之前,请阅读邮件列表存档中关于这些提议的历史记录。此外,请准备好接受挑战,提供一个可行的原型。

5.4. 分发文件

Makefile 的第二部分描述了构建端口必须下载的文件,以及在哪里可以下载这些文件。

5.4.1. DISTNAME

DISTNAME 是软件作者所称的端口名称。DISTNAME 默认为 ${PORTNAME}-${DISTVERSIONPREFIX}${DISTVERSION}${DISTVERSIONSUFFIX},如果未设置,则 DISTVERSION 默认为 ${PORTVERSION},因此仅在必要时覆盖 DISTNAMEDISTNAME 仅在两个地方使用。首先,分发文件列表 (DISTFILES) 默认为 ${DISTNAME}${EXTRACT_SUFX}。其次,预期分发文件将解压缩到名为 WRKSRC 的子目录中,该子目录默认为 work/${DISTNAME}

某些供应商的分发名称不符合 ${PORTNAME}-${PORTVERSION} 方案,可以通过设置 DISTVERSIONPREFIXDISTVERSIONDISTVERSIONSUFFIX 自动处理。PORTVERSION 将自动从 DISTVERSION 派生。

一次只能设置 PORTVERSIONDISTVERSION 中的一个。如果 DISTVERSION 无法派生正确的 PORTVERSION,请不要使用 DISTVERSION

如果上游版本方案可以派生为端口兼容的版本方案,请将某个变量设置为上游版本,不要使用 DISTVERSION 作为变量名。根据您创建的变量设置 PORTVERSION 为计算出的版本,并相应地设置 DISTNAME

如果上游版本方案不容易强制转换为端口兼容的值,请将 PORTVERSION 设置为合理的值,并使用 PORTNAME 和上游版本的逐字版本设置 DISTNAME

示例 6. 手动派生 PORTVERSION

BIND9 使用的版本方案与端口版本不兼容(在其版本中包含 -),并且无法使用 DISTVERSION 派生,因为在 9.9.9 版本发布后,它将以 9.9.9-P1 的形式发布“补丁级别”。DISTVERSION 会将其转换为 9.9.9.p1,这在端口版本方案中表示 9.9.9 预发布 1,它在 9.9.9 之前而不是之后。因此,PORTVERSION 是从 ISCVERSION 变量手动派生而来以输出 9.9.9p1

使用 pkg-version(8)-t 参数检查端口框架和 pkg 将对版本进行排序的顺序。

% pkg version -t 9.9.9 9.9.9.p1
> (1)
% pkg version -t 9.9.9 9.9.9p1
< (2)
1> 符号表示传递给 -t 的第一个参数大于第二个参数。9.9.99.9.9.p1 之后。
2< 符号表示传递给 -t 的第一个参数小于第二个参数。9.9.99.9.9p1 之前。

例如,在端口 Makefiledns/bind99,它是通过以下方式实现的

PORTNAME=	bind
PORTVERSION=	${ISCVERSION:S/-P/P/:S/b/.b/:S/a/.a/:S/rc/.rc/}
CATEGORIES=	dns net
MASTER_SITES=	ISC/bind9/${ISCVERSION}
PKGNAMESUFFIX=	99
DISTNAME=	${PORTNAME}-${ISCVERSION}

MAINTAINER=	[email protected]
COMMENT=	BIND DNS suite with updated DNSSEC and DNS64
WWW=		https://www.isc.org/bind/

LICENSE=	ISCL

# ISC releases things like 9.8.0-P1 or 9.8.1rc1, which our versioning does not like
ISCVERSION=	9.9.9-P6

ISCVERSION 中定义上游版本,并添加注释说明为什么需要它。使用 ISCVERSION 获取端口兼容的 PORTVERSION。直接使用 ISCVERSION 获取获取分发文件的正确 URL。直接使用 ISCVERSION 为分发文件命名。

示例 7. 从 PORTVERSION 派生 DISTNAME

有时,分发文件的名称与软件的版本几乎没有关系。

comms/kermit 中,版本中的最后一个元素存在于分发文件中

PORTNAME=	kermit
PORTVERSION=	9.0.304
CATEGORIES=	comms ftp net
MASTER_SITES=	ftp://ftp.kermitproject.org/kermit/test/tar/
DISTNAME=	cku${PORTVERSION:E}-dev20

:E make(1) 修饰符返回变量的后缀,在本例中为 304。分发文件正确生成,为 cku304-dev20.tar.gz

示例 8. 奇特情况 1

有时,软件名称、其版本及其分发文件之间没有关系。

PORTNAME=       libworkman
PORTVERSION=    1.4
CATEGORIES=     audio
MASTER_SITES=   LOCAL/jim
DISTNAME=       ${PORTNAME}-1999-06-20
示例 9. 奇特情况 2

comms/librs232 中,分发文件未版本化,因此需要使用 DIST_SUBDIR

PORTNAME=       librs232
PORTVERSION=    20160710
CATEGORIES=     comms
MASTER_SITES=   http://www.teuniz.net/RS-232/
DISTNAME=       RS-232
DIST_SUBDIR=	${PORTNAME}-${PORTVERSION}

PKGNAMEPREFIXPKGNAMESUFFIX 不影响 DISTNAME。另请注意,如果 WRKSRC 等于 ${WRKDIR}/${DISTNAME},而原始源归档文件的名称不是 ${PORTNAME}-${PORTVERSION}${EXTRACT_SUFX},则保持 DISTNAME 不变 - 只定义 DISTFILES 比定义 DISTNAMEWRKSRC(以及可能 EXTRACT_SUFX)更容易。

5.4.2. MASTER_SITES

MASTER_SITES 中记录指向原始 tarball 的 FTP/HTTP-URL 的目录部分。不要忘记尾部斜杠 (/)!

如果 make 宏在系统上找不到分发文件,则会尝试使用此规范使用 FETCH 获取它。

建议在此列表中包含多个站点,最好来自不同的大陆。这将防止广域网出现问题。

MASTER_SITES 不能为空。它必须指向托管分发文件的实际站点。它不能指向 Web 档案或 FreeBSD 分发文件缓存站点。此规则的唯一例外是没有任何分发文件的端口。例如,元端口没有任何分发文件,因此不需要设置 MASTER_SITES

5.4.2.1. 使用 MASTER_SITE_* 变量

对于 SourceForge (SOURCEFORGE)、GNU (GNU) 或 Perl CPAN (PERL_CPAN) 等常用存档,可以使用快捷方式缩写。MASTER_SITES 可以直接使用它们

MASTER_SITES=	GNU/make

旧的扩展格式仍然有效,但所有端口都已转换为紧凑格式。扩展格式如下所示

MASTER_SITES=		${MASTER_SITE_GNU}
MASTER_SITE_SUBDIR=	make

这些值和变量在 Mk/bsd.sites.mk 中定义。经常会添加新条目,因此在提交端口之前,请确保检查此文件的最新版本。

对于任何 MASTER_SITE_FOO 变量,都可以使用缩写 FOO。例如,使用

MASTER_SITES=	FOO

如果需要 MASTER_SITE_SUBDIR,请使用以下命令

MASTER_SITES=	FOO/bar

一些 MASTER_SITE_* 名称非常长,为了方便使用,已定义了快捷方式

表 3. MASTER_SITE_* 宏的快捷方式
快捷方式

PERL_CPAN

CPAN

GITHUB

GH

GITHUB_CLOUD

GHC

LIBREOFFICE_DEV

LODEV

NETLIB

NL

RUBYGEMS

RG

SOURCEFORGE

SF

5.4.2.2. 魔术 MASTER_SITES 宏

对于具有可预测目录结构的常用站点,存在多个“魔术”宏。对于这些宏,只需使用缩写,系统将自动选择子目录。对于名为 Stardict、版本为 1.2.3 并托管在 SourceForge 上的端口,添加以下行

MASTER_SITES=	SF

推断名为 /project/stardict/stardict/1.2.3 的子目录。如果推断的目录不正确,可以覆盖它

MASTER_SITES=	SF/stardict/WyabdcRealPeopleTTS/${PORTVERSION}

这也可以写成

MASTER_SITES=	SF
MASTER_SITE_SUBDIR=	stardict/WyabdcRealPeopleTTS/${PORTVERSION}

5.4.3. USE_GITHUB

如果分发文件来自 GitHub 上的特定提交或标签,并且没有正式发布的文件,则有一种简单的方法可以自动设置正确的 DISTNAMEMASTER_SITES

截至 2023-02-21 GitHub 宣布源代码下载将在一年内保持稳定。请切换到发布资源,如果不可用,请请求上游生成资源。

以下变量可用

表 5. USE_GITHUB 描述
变量描述默认值

GH_ACCOUNT

托管项目的 GitHub 用户的帐户名称

${PORTNAME}

GH_PROJECT

GitHub 上项目的名称

${PORTNAME}

GH_TAGNAME

要下载的标签的名称 (2.0.1、哈希等) 在此处使用分支名称是不正确的。也可以使用提交 ID 的哈希值进行快照。

${DISTVERSIONPREFIX}${DISTVERSION}${DISTVERSIONSUFFIX}

GH_SUBDIR

当软件需要在 ${WRKSRC} 中提取其他分发文件时,可以使用此变量。有关更多信息,请参阅 从 GitHub 获取多个文件 中的示例。

(无)

GH_TUPLE

GH_TUPLE 允许将 GH_ACCOUNTGH_PROJECTGH_TAGNAMEGH_SUBDIR 放入单个变量中。格式为 account`:`project`:`tagname`:`group`/`subdir。`/`subdir 部分是可选的。当需要从多个 GitHub 项目中获取文件时,它很有帮助。

不要将 GH_TUPLE 用于默认发行文件,因为它没有默认值。

示例 10. USE_GITHUB 的简单用法

在尝试为 github 上 FreeBSD 用户的 pkg 的 1.2.7 版本制作端口时,位于 https://github.com/freebsd/pkg/Makefile 最终将如下所示(为示例略微简化)

PORTNAME=	pkg
DISTVERSION=	1.2.7

USE_GITHUB=	yes
GH_ACCOUNT=	freebsd

它将自动将 MASTER_SITES 设置为 GH,并将 WRKSRC 设置为 ${WRKDIR}/pkg-1.2.7

示例 11. USE_GITHUB 的更完整用法

在尝试为 github 上 FreeBSD 用户的 pkg 的 bleeding edge 版本制作端口时,位于 https://github.com/freebsd/pkg/Makefile 最终将如下所示(为示例略微简化)

PORTNAME=	pkg-devel
DISTVERSION=	1.3.0.a.20140411

USE_GITHUB=	yes
GH_ACCOUNT=	freebsd
GH_PROJECT=	pkg
GH_TAGNAME=	6dbb17b

它将自动将 MASTER_SITES 设置为 GH,并将 WRKSRC 设置为 ${WRKDIR}/pkg-6dbb17b

20140411GH_TAGNAME 中引用的提交日期,而不是 Makefile 被编辑的日期,也不是提交创建的日期。

示例 12. USE_GITHUBDISTVERSIONPREFIX 的用法

有时,GH_TAGNAMEDISTVERSION 略有不同。例如,如果版本为 1.0.2,则标签为 v1.0.2。在这些情况下,可以使用 DISTVERSIONPREFIXDISTVERSIONSUFFIX

PORTNAME=	foo
DISTVERSIONPREFIX=	v
DISTVERSION=	1.0.2

USE_GITHUB=	yes

它将自动将 GH_TAGNAME 设置为 v1.0.2,而 WRKSRC 将保持为 ${WRKDIR}/foo-1.0.2

示例 13. 上游未使用版本时 USE_GITHUB 的用法

如果上游从未有过版本,不要像 0.11.0 一样发明一个版本。使用 DISTVERSIONgYYYYMMDD 创建端口,其中 g 代表 Git,YYYYMMDD 表示 GH_TAGNAME 中引用的提交日期。

PORTNAME=	bar
DISTVERSION=	g20140411

USE_GITHUB=	yes
GH_TAGNAME=	c472d66b

这创建了一个随时间推移而增加的版本方案,并且仍然在版本 0 之前(有关版本比较的详细信息,请参阅 使用 pkg-version\(8] 比较版本) 中有关 pkg-version(8) 的信息)

% pkg version -t g20140411 0
<

这意味着如果上游将来决定发布版本,则不需要使用 PORTEPOCH

示例 14. 使用 USE_GITHUB 访问两个版本之间的提交

如果软件的当前版本使用 Git 标签,并且端口需要更新到没有标签的较新中间版本,请使用 git-describe(1) 找出要使用的版本

% git describe --tags f0038b1
v0.7.3-14-gf0038b1

v0.7.3-14-gf0038b1 可以分成三个部分

v0.7.3

这是在请求的提交之前的提交历史记录中出现的最后一个 Git 标签。

-14

这意味着请求的提交 f0038b1v0.7.3 标签之后的第 14 个提交。

-gf0038b1

-g 表示“Git”,f0038b1 是此引用指向的提交哈希。

PORTNAME=	bar
DISTVERSIONPREFIX=  v
DISTVERSION=	0.7.3-14
DISTVERSIONSUFFIX=  -gf0038b1

USE_GITHUB=	yes

这创建了一个随时间推移(或者说随提交次数)而增加的版本方案,并且不会与创建 0.7.4 版本冲突。(有关版本比较的详细信息,请参阅 使用 pkg-version\(8] 比较版本) 中有关 pkg-version(8) 的信息)

% pkg version -t 0.7.3 0.7.3.14
<
% pkg version -t 0.7.3.14 0.7.4
<

如果请求的提交与标签相同,则默认情况下会显示较短的描述。较长的版本是等效的

% git describe --tags c66c71d
v0.7.3

% git describe --tags --long c66c71d
v0.7.3-0-gc66c71d

5.4.3.1. 从 GitHub 获取多个文件

USE_GITHUB 框架还支持从 GitHub 中的不同位置获取多个发行文件。它的工作方式与 从多个位置获取多个发行或补丁文件 非常相似。

多个值将添加到 GH_ACCOUNTGH_PROJECTGH_TAGNAME 中。每个不同的值都被分配一个组。主值可以没有组,也可以具有 :DEFAULT 组。如果某个值与 USE_GITHUB 描述 中列出的默认值相同,则可以省略该值。

当存在大量发行文件时,也可以使用 GH_TUPLE。它有助于将帐户、项目、标签名称和组信息保存在同一位置。

对于每个组,都会创建一个 ${WRKSRC_group} 帮助器变量,其中包含已提取文件的目录。${WRKSRC_group} 变量可用于在 post-extract 期间移动目录,或添加到 CONFIGURE_ARGS 中,或执行任何其他必要的操作,以便软件能够正确构建。

:group 部分 *必须* *仅用于一个* 发行文件。它用作唯一的键,多次使用它将覆盖以前的值。

由于这只是 DISTFILESMASTER_SITES 之上的语法糖,因此组名称必须符合 从多个位置获取多个发行或补丁文件 中概述的组名称限制。

当从 GitHub 获取多个文件时,有时不会从 GitHub 获取默认发行文件。要禁用获取默认发行文件,请设置

USE_GITHUB=	nodefault

当使用 USE_GITHUB=nodefault 时,Makefile 必须在其 顶部块 中设置 DISTFILES。定义应为

DISTFILES=    ${DISTNAME}${EXTRACT_SUFX}
示例 15. 使用 USE_GITHUB 获取多个发行文件

有时需要获取多个发行文件。例如,当上游 git 存储库使用子模块时。这可以使用 GH_* 变量中的组轻松完成

PORTNAME=	foo
DISTVERSION=	1.0.2

USE_GITHUB=	yes
GH_ACCOUNT=	bar:icons,contrib
GH_PROJECT=	foo-icons:icons foo-contrib:contrib
GH_TAGNAME=	1.0:icons fa579bc:contrib
GH_SUBDIR=	ext/icons:icons

CONFIGURE_ARGS=	--with-contrib=${WRKSRC_contrib}

这将从 github 获取三个发行文件。默认文件来自 foo/foo,版本为 1.0.2。第二个文件(具有 icons 组)来自 bar/foo-icons,版本为 1.0。第三个文件来自 bar/foo-contrib,并使用 Git 提交 fa579bc。发行文件的名称为 foo-foo-1.0.2_GH0.tar.gzbar-foo-icons-1.0_GH0.tar.gzbar-foo-contrib-fa579bc_GH0.tar.gz

所有发行文件都解压缩到 ${WRKDIR} 中各自的子目录中。默认文件仍然解压缩到 ${WRKSRC} 中,在本例中为 ${WRKDIR}/foo-1.0.2。每个额外的发行文件都解压缩到 ${WRKSRC_group} 中。这里,对于 icons 组,它被称为 ${WRKSRC_icons},它包含 ${WRKDIR}/foo-icons-1.0。具有 contrib 组的文件被称为 ${WRKSRC_contrib},它包含 ${WRKDIR}/foo-contrib-fa579bc

软件的构建系统期望在其源代码的 ext/icons 子目录中找到图标,因此使用了 GH_SUBDIRGH_SUBDIR 确保 ext 存在,但 ext/icons 不存在。然后它执行以下操作

post-extract:
      @${MV} ${WRKSRC_icons} ${WRKSRC}/ext/icons
示例 16. 使用 USE_GITHUB 获取多个发行文件,并使用 GH_TUPLE

这在功能上等效于 使用 USE_GITHUB 获取多个发行文件,但使用了 GH_TUPLE

PORTNAME=	foo
DISTVERSION=	1.0.2

USE_GITHUB=	yes
GH_TUPLE=	bar:foo-icons:1.0:icons/ext/icons \
		bar:foo-contrib:fa579bc:contrib

CONFIGURE_ARGS=	--with-contrib=${WRKSRC_contrib}

在前面的示例中,使用了 bar:icons,contrib 进行分组。由于 GH_TUPLE 不支持分组,因此存在一些冗余信息。

示例 17. 如何将 USE_GITHUB 与 Git 子模块一起使用?

将 GitHub 作为上游存储库的端口有时会使用子模块。有关更多信息,请参阅 git-submodule(1)

子模块的问题在于每个子模块都是一个单独的存储库。因此,必须分别获取它们。

finance/moneymanagerex 为例,其 GitHub 存储库为 https://github.com/moneymanagerex/moneymanagerex/。它在根目录下有一个 .gitmodules 文件。此文件描述了在此存储库中使用的所有子模块,并列出了所需的额外存储库。此文件将说明需要哪些其他存储库

[submodule "lib/wxsqlite3"]
	path = lib/wxsqlite3
	url = https://github.com/utelle/wxsqlite3.git
[submodule "3rd/mongoose"]
	path = 3rd/mongoose
	url = https://github.com/cesanta/mongoose.git
[submodule "3rd/LuaGlue"]
	path = 3rd/LuaGlue
	url = https://github.com/moneymanagerex/LuaGlue.git
[submodule "3rd/cgitemplate"]
	path = 3rd/cgitemplate
	url = https://github.com/moneymanagerex/html-template.git
[...]

该文件中唯一缺少的信息是作为版本使用的提交哈希或标签。此信息在克隆存储库后找到

% git clone --recurse-submodules https://github.com/moneymanagerex/moneymanagerex.git
Cloning into 'moneymanagerex'...
remote: Counting objects: 32387, done.
[...]
Submodule '3rd/LuaGlue' (https://github.com/moneymanagerex/LuaGlue.git) registered for path '3rd/LuaGlue'
Submodule '3rd/cgitemplate' (https://github.com/moneymanagerex/html-template.git) registered for path '3rd/cgitemplate'
Submodule '3rd/mongoose' (https://github.com/cesanta/mongoose.git) registered for path '3rd/mongoose'
Submodule 'lib/wxsqlite3' (https://github.com/utelle/wxsqlite3.git) registered for path 'lib/wxsqlite3'
[...]
Cloning into '/home/mat/work/freebsd/ports/finance/moneymanagerex/moneymanagerex/3rd/LuaGlue'...
Cloning into '/home/mat/work/freebsd/ports/finance/moneymanagerex/moneymanagerex/3rd/cgitemplate'...
Cloning into '/home/mat/work/freebsd/ports/finance/moneymanagerex/moneymanagerex/3rd/mongoose'...
Cloning into '/home/mat/work/freebsd/ports/finance/moneymanagerex/moneymanagerex/lib/wxsqlite3'...
[...]
Submodule path '3rd/LuaGlue': checked out 'c51d11a247ee4d1e9817dfa2a8da8d9e2f97ae3b'
Submodule path '3rd/cgitemplate': checked out 'cd434eeeb35904ebcd3d718ba29c281a649b192c'
Submodule path '3rd/mongoose': checked out '2140e5992ab9a3a9a34ce9a281abf57f00f95cda'
Submodule path 'lib/wxsqlite3': checked out 'fb66eb230d8aed21dec273b38c7c054dcb7d6b51'
[...]
% cd moneymanagerex
% git submodule status
 c51d11a247ee4d1e9817dfa2a8da8d9e2f97ae3b 3rd/LuaGlue (heads/master)
 cd434eeeb35904ebcd3d718ba29c281a649b192c 3rd/cgitemplate (cd434ee)
 2140e5992ab9a3a9a34ce9a281abf57f00f95cda 3rd/mongoose (6.2-138-g2140e59)
 fb66eb230d8aed21dec273b38c7c054dcb7d6b51 lib/wxsqlite3 (v3.4.0)
[...]

它也可以在 GitHub 上找到。每个作为子模块的子目录都显示为 directory @ hash,例如 mongoose @ 2140e59

虽然从 GitHub 获取信息似乎更简单,但使用 git submodule status 找到的信息将提供更有意义的信息。例如,这里 lib/wxsqlite3 的提交哈希 fb66eb2 对应于 v3.4.0。两者可以互换使用,但当有标签可用时,请使用标签。

现在所有必要的信息都已收集完毕,可以编写 Makefile 了(仅显示与 GitHub 相关的行)

PORTNAME=	moneymanagerex
DISTVERSIONPREFIX=	v
DISTVERSION=	1.3.0

USE_GITHUB=	yes
GH_TUPLE=	utelle:wxsqlite3:v3.4.0:wxsqlite3/lib/wxsqlite3 \
		moneymanagerex:LuaGlue:c51d11a:lua_glue/3rd/LuaGlue \
		moneymanagerex:html-template:cd434ee:html_template/3rd/cgitemplate \
		cesanta:mongoose:2140e59:mongoose/3rd/mongoose \
		[...]

5.4.4. USE_GITLAB

与 GitHub 类似,如果发行文件来自 gitlab.com 或托管 GitLab 软件,则可以使用这些变量,并且可能需要设置它们。

表 6. USE_GITLAB 描述
变量描述默认值

GL_SITE

托管 GitLab 项目的站点名称

https://gitlab.com/

GL_ACCOUNT

托管项目的 GitLab 用户的帐户名称

${PORTNAME}

GL_PROJECT

GitLab 上项目的名称

${PORTNAME}

GL_COMMIT

要下载的提交哈希。必须是完整的 160 位,40 个字符的十六进制 sha1 哈希。这是 GitLab 的必填变量。

(无)

GL_SUBDIR

当软件需要将其他发行文件解压缩到 ${WRKSRC} 中时,可以使用此变量。有关更多信息,请参阅 从 GitLab 获取多个文件 中的示例。

(无)

GL_TUPLE

GL_TUPLE 允许将 GL_SITEGL_ACCOUNTGL_PROJECTGL_COMMITGL_SUBDIR 放入单个变量中。格式为 site`:`account`:`project`:`commit`:`group`/subdirsite:` 和 `/`subdir 部分是可选的。当需要从多个 GitLab 项目中获取文件时,它很有帮助。

示例 18. USE_GITLAB 的简单用法

在尝试为 gitlab.com 上 accounts-sso 用户的 libsignon-glib 的 1.14 版本制作端口时,位于 https://gitlab.com/accounts-sso/libsignon-glib/,获取发行文件的 Makefile 将如下所示

PORTNAME=	libsignon-glib
DISTVERSION=	1.14

USE_GITLAB=	yes
GL_ACCOUNT=	accounts-sso
GL_COMMIT=	e90302e342bfd27bc8c9132ab9d0ea3d8723fd03

它将自动将MASTER_SITES设置为gitlab.com,并将WRKSRC设置为${WRKDIR}/libsignon-glib-e90302e342bfd27bc8c9132ab9d0ea3d8723fd03-e90302e342bfd27bc8c9132ab9d0ea3d8723fd03

示例 19. 更完整的 USE_GITLAB 使用方法

如果端口没有版本控制,并且 foo 用户在自托管 GitLab 站点https://gitlab.example.com/上的 bar 项目中拥有 foobar,则用于获取分发文件的 Makefile 最终看起来像这样

PORTNAME=	foobar
DISTVERSION=	g20170906

USE_GITLAB=	yes
GL_SITE=	https://gitlab.example.com
GL_ACCOUNT=	foo
GL_PROJECT=	bar
GL_COMMIT=	9c1669ce60c3f4f5eb43df874d7314483fb3f8a6

它将把MASTER_SITES设置为"https://gitlab.example.com",并将WRKSRC设置为${WRKDIR}/bar-9c1669ce60c3f4f5eb43df874d7314483fb3f8a6-9c1669ce60c3f4f5eb43df874d7314483fb3f8a6

20170906GL_COMMIT 中引用的提交日期,而不是 Makefile 被编辑的日期,也不是对 FreeBSD 端口树进行提交的日期。

可以在同一个变量中修改GL_SITE的协议、端口和 Web 根目录。

5.4.4.1. 从 GitLab 获取多个文件

USE_GITLAB 框架还支持从 GitLab 和 GitLab 托管站点上的不同位置获取多个分发文件。它的工作方式与从多个位置获取多个分发文件或补丁文件从 GitLab 获取多个文件非常相似。

多个值被添加到GL_SITEGL_ACCOUNTGL_PROJECTGL_COMMIT中。每个不同的值都被分配一个组。USE_GITLAB 说明

当存在大量分发文件时,也可以使用GL_TUPLE。它有助于将站点、帐户、项目、提交和组信息保留在同一位置。

对于每个组,都会创建一个 ${WRKSRC_group} 帮助器变量,其中包含已提取文件的目录。${WRKSRC_group} 变量可用于在 post-extract 期间移动目录,或添加到 CONFIGURE_ARGS 中,或执行任何其他必要的操作,以便软件能够正确构建。

:group 部分 *必须* *仅用于一个* 发行文件。它用作唯一的键,多次使用它将覆盖以前的值。

由于这只是 DISTFILESMASTER_SITES 之上的语法糖,因此组名称必须符合 从多个位置获取多个发行或补丁文件 中概述的组名称限制。

当使用 GitLab 获取多个文件时,有时默认分发文件不会从 GitLab 站点获取。要禁用获取默认分发文件,请设置

USE_GITLAB=	nodefault

当使用USE_GITLAB=nodefault时,Makefile必须在其顶部块中设置DISTFILES。定义应为

DISTFILES=    ${DISTNAME}${EXTRACT_SUFX}
示例 20. 使用带有多个分发文件的USE_GITLAB

有时,需要获取多个分发文件。例如,当上游 Git 存储库使用子模块时。这可以通过在GL_*变量中使用组轻松完成

PORTNAME=	foo
DISTVERSION=	1.0.2

USE_GITLAB=	yes
GL_SITE=	https://gitlab.example.com:9434/gitlab:icons
GL_ACCOUNT=	bar:icons,contrib
GL_PROJECT=	foo-icons:icons foo-contrib:contrib
GL_COMMIT=	c189207a55da45305c884fe2b50e086fcad4724b ae7368cab1ca7ca754b38d49da064df87968ffe4:icons 9e4dd76ad9b38f33fdb417a4c01935958d5acd2a:contrib
GL_SUBDIR=	ext/icons:icons

CONFIGURE_ARGS= --with-contrib=${WRKSRC_contrib}

这将从 gitlab.com 获取两个分发文件,并从托管 GitLab 的gitlab.example.com获取一个分发文件。默认文件来自https://gitlab.com/foo/foo,提交为c189207a55da45305c884fe2b50e086fcad4724b。第二个文件(带有icons组)来自https://gitlab.example.com:9434/gitlab/bar/foo-icons,提交为ae7368cab1ca7ca754b38d49da064df87968ffe4。第三个文件来自https://gitlab.com/bar/foo-contrib,提交为9e4dd76ad9b38f33fdb417a4c01935958d5acd2a。分发文件分别命名为foo-foo-c189207a55da45305c884fe2b50e086fcad4724b_GL0.tar.gzbar-foo-icons-ae7368cab1ca7ca754b38d49da064df87968ffe4_GL0.tar.gzbar-foo-contrib-9e4dd76ad9b38f33fdb417a4c01935958d5acd2a_GL0.tar.gz

所有分发文件都解压缩到${WRKDIR}中各自的子目录中。默认文件仍然解压缩到${WRKSRC}中,在本例中为${WRKDIR}/foo-c189207a55da45305c884fe2b50e086fcad4724b-c189207a55da45305c884fe2b50e086fcad4724b。每个额外的分发文件都解压缩到${WRKSRC_group}中。这里,对于icons组,它被称为${WRKSRC_icons},它包含${WRKDIR}/foo-icons-ae7368cab1ca7ca754b38d49da064df87968ffe4-ae7368cab1ca7ca754b38d49da064df87968ffe4。带有contrib组的文件被称为${WRKSRC_contrib},它包含${WRKDIR}/foo-contrib-9e4dd76ad9b38f33fdb417a4c01935958d5acd2a-9e4dd76ad9b38f33fdb417a4c01935958d5acd2a

软件的构建系统期望在源代码的ext/icons子目录中找到图标,因此使用GL_SUBDIRGL_SUBDIR确保ext存在,但ext/icons不存在。然后它执行以下操作

post-extract:
        @${MV} ${WRKSRC_icons} ${WRKSRC}/ext/icons
示例 21. 使用GL_TUPLE的带有多个分发文件的USE_GITLAB

这在功能上等同于使用带有多个分发文件的USE_GITLAB,但使用了GL_TUPLE

PORTNAME=	foo
DISTVERSION=	1.0.2

USE_GITLAB=	yes
GL_COMMIT=	c189207a55da45305c884fe2b50e086fcad4724b
GL_TUPLE=	https://gitlab.example.com:9434/gitlab:bar:foo-icons:ae7368cab1ca7ca754b38d49da064df87968ffe4:icons/ext/icons \
		bar:foo-contrib:9e4dd76ad9b38f33fdb417a4c01935958d5acd2a:contrib

CONFIGURE_ARGS= --with-contrib=${WRKSRC_contrib}

在前面的示例中使用了bar:icons,contrib进行分组。由于无法进行分组,因此GL_TUPLE中存在一些冗余信息。

5.4.5. EXTRACT_SUFX

如果只有一个分发文件,并且它使用奇特的扩展名来指示压缩机制,请设置EXTRACT_SUFX

例如,如果分发文件名为foo.tar.gzip而不是更常见的foo.tar.gz,请写入

DISTNAME=	foo
EXTRACT_SUFX=	.tar.gzip

USES=tar[:xxx]USES=lhaUSES=zip会根据需要自动将EXTRACT_SUFX设置为最常见的归档文件扩展名,有关更多详细信息,请参阅使用USES。如果这两个都没有设置,则EXTRACT_SUFX默认为.tar.gz

由于EXTRACT_SUFX仅在DISTFILES中使用,因此只需设置其中一个即可。

5.4.6. DISTFILES

有时,要下载的文件的名称与端口的名称没有任何相似之处。例如,它可能被称为source.tar.gz或类似名称。在其他情况下,应用程序的源代码可能位于多个不同的归档文件中,所有这些文件都必须下载。

如果是这种情况,请将DISTFILES设置为要下载的所有文件的空格分隔列表。

DISTFILES=	source1.tar.gz source2.tar.gz

如果未显式设置,则DISTFILES默认为${DISTNAME}${EXTRACT_SUFX}

5.4.7. EXTRACT_ONLY

如果只需要提取某些DISTFILES——例如,其中一个文件是源代码,而另一个文件是未压缩的文档——请在EXTRACT_ONLY中列出必须提取的文件名。

DISTFILES=	source.tar.gz manual.html
EXTRACT_ONLY=	source.tar.gz

当不需要解压缩任何DISTFILES时,请将EXTRACT_ONLY设置为空字符串。

EXTRACT_ONLY=

5.4.8. PATCHFILES

如果端口需要一些通过 FTP 或 HTTP 可用的额外补丁,请将PATCHFILES设置为文件的名称,并将PATCH_SITES设置为包含它们的目录的 URL(格式与MASTER_SITES相同)。

如果补丁不是相对于源代码树的顶部(即WRKSRC),因为它包含一些额外的路径名,请相应地设置PATCH_DIST_STRIP。例如,如果补丁中的所有路径名前面都有一个额外的foozolix-1.0/,则设置PATCH_DIST_STRIP=-p1

如果补丁已压缩,请不要担心;如果文件名以.Z.gz.bz2.xz结尾,它们将自动解压缩。

如果补丁与其他一些文件(如文档)一起打包在压缩的 tarball 中,则无法使用PATCHFILES。如果是这种情况,请将补丁 tarball 的名称和位置添加到DISTFILESMASTER_SITES中。然后,使用EXTRA_PATCHES指向这些文件,bsd.port.mk将自动应用它们。特别是,**不要**将补丁文件复制到${PATCHDIR}中。该目录可能不可写。

如果有多个补丁,并且它们需要混合的 strip 参数值,则可以将其与PATCHFILES中的补丁名称一起添加,例如

PATCHFILES=	patch1 patch2:-p1

这不会与主站点分组功能冲突,添加组也有效

PATCHFILES=	patch2:-p1:source2

到那时,tarball 将已与常规源代码一起解压缩,因此如果它是常规压缩的 tarball,则无需显式解压缩它。如果手动解压缩,请格外小心,不要覆盖该目录中已存在的内容。此外,不要忘记在pre-clean目标中添加一个删除已复制补丁的命令。

5.4.9. 从多个位置获取多个分发文件或补丁文件

(可以将此视为一个“高级主题”;初次阅读本文档的用户可能希望先跳过本节)。

本节介绍了称为MASTER_SITES:nMASTER_SITES_NN的获取机制。我们将此机制称为MASTER_SITES:n

首先简要介绍一下背景。OpenBSD 在DISTFILESPATCHFILES中有一个巧妙的功能,允许在文件和补丁后面附加:n标识符。这里,n可以是包含[0-9a-zA-Z_]的任何单词,并表示一个组名称。例如

DISTFILES=	alpha:0 beta:1

在 OpenBSD 中,分发文件alpha将与变量MASTER_SITES0关联,而不是我们常见的MASTER_SITES,而beta将与MASTER_SITES1关联。

这是一个非常有趣的功能,可以减少对正确下载站点的无尽搜索。

试想一下,DISTFILES中有 2 个文件,MASTER_SITES中有 20 个站点,这些站点速度非常慢,其中betaMASTER_SITES中的所有站点承载,而alpha只能在第 20 个站点中找到。如果维护人员事先知道这一点,检查所有站点将是多么浪费,不是吗?对美好的周末来说不是一个好的开始!

现在您有了这个想法,只需想象更多DISTFILES和更多MASTER_SITES。当然,我们的“分发文件调查大师”会感谢这带来的网络压力缓解。

在接下来的部分中,将介绍此想法在 FreeBSD 中的实现信息。我们对 OpenBSD 的概念进行了一些改进。

组名中不能包含连字符(-),实际上,它们不能包含[a-zA-Z0-9_]范围之外的任何字符。这是因为,虽然make(1)可以接受包含连字符的变量名,但sh(1)不可以。

5.4.9.1. 简化信息

本节说明如何快速准备从不同站点和子目录获取多个分发文件和补丁的细粒度获取。我们在此描述了一个简化的MASTER_SITES:n使用案例。这对于大多数场景来说已经足够了。更多详细信息请参阅详细信息

某些应用程序包含必须从多个不同站点下载的多个分发文件。例如,Ghostscript 包含程序的核心,然后是大量驱动程序文件,这些文件根据用户的打印机使用。其中一些驱动程序文件与核心一起提供,但许多其他文件必须从各种不同的站点下载。

为了支持这一点,DISTFILES中的每个条目后面都可以跟一个冒号和一个“组名”。然后,MASTER_SITES中列出的每个站点后面都跟着一个冒号,以及指示从该站点下载哪些分发文件的组。

例如,考虑一个应用程序,其源代码分为两部分,source1.tar.gzsource2.tar.gz,它们必须从两个不同的站点下载。端口的Makefile将包含类似于每个站点一个文件的简化MASTER_SITES:n使用的行。

示例 22. 使用MASTER_SITES:n简化每个站点一个文件的用法
MASTER_SITES=	ftp://ftp1.example.com/:source1 \
		http://www.example.com/:source2
DISTFILES=	source1.tar.gz:source1 \
		source2.tar.gz:source2

多个分发文件可以具有相同的组。继续前面的示例,假设存在第三个 distfile,source3.tar.gz,它从ftp.example2.com下载。然后,Makefile 将编写如下使用MASTER_SITES:n简化每个站点多个文件的用法

示例 23. 使用MASTER_SITES:n简化每个站点多个文件的用法
MASTER_SITES=	ftp://ftp.example.com/:source1 \
		http://www.example.com/:source2
DISTFILES=	source1.tar.gz:source1 \
		source2.tar.gz:source2 \
		source3.tar.gz:source2

5.4.9.2. 详细的信息

好的,那么前面的示例没有反映新端口的需求?在本节中,我们将详细解释细粒度获取机制MASTER_SITES:n的工作原理以及如何使用它。

  1. 元素可以后缀:n,其中n`, 即,_n_ 概念上可以是任何字母数字字符串,但我们目前将其限制为`[a-zA-Z_][0-9a-zA-Z_]

    此外,字符串匹配区分大小写;也就是说,nN不同。

    但是,这些词不能用于后缀目的,因为它们具有特殊含义:defaultallALL(它们在项目ii中内部使用)。此外,DEFAULT是一个特殊用途的词(请查看项目3)。

  2. 后缀为:n的元素属于组n:m属于组m,依此类推。

  3. 没有后缀的元素是无组的,它们都属于特殊组DEFAULT。任何后缀为DEFAULT的元素都是多余的,除非一个元素同时属于DEFAULT和其他组(请查看项目5)。

    这些示例是等价的,但第一个示例更受欢迎

    MASTER_SITES=	alpha
    MASTER_SITES=	alpha:DEFAULT
  4. 组不是互斥的,一个元素可以同时属于几个不同的组,一个组可以具有几个不同的元素或根本没有元素。

  5. 当一个元素同时属于多个组时,使用逗号运算符(,)。

    与其多次重复,每次使用不同的后缀,不如在单个后缀中一次列出多个组。例如,:m,n,o标记属于组mno的元素。

    所有这些示例都是等价的,但最后一个示例更受欢迎

    MASTER_SITES=	alpha alpha:SOME_SITE
    MASTER_SITES=	alpha:DEFAULT alpha:SOME_SITE
    MASTER_SITES=	alpha:SOME_SITE,DEFAULT
    MASTER_SITES=	alpha:DEFAULT,SOME_SITE
  6. 给定组中的所有站点都根据MASTER_SORT_AWK排序。MASTER_SITESPATCH_SITES中的所有组也都会排序。

  7. 组语义可以在任何变量MASTER_SITESPATCH_SITESMASTER_SITE_SUBDIRPATCH_SITE_SUBDIRDISTFILESPATCHFILES中使用,语法如下

    1. 所有MASTER_SITESPATCH_SITESMASTER_SITE_SUBDIRPATCH_SITE_SUBDIR元素必须以正斜杠/字符结尾。如果任何元素属于任何组,则组后缀:n必须紧跟在终止符/之后。MASTER_SITES:n机制依赖于终止符/的存在,以避免将:n是元素有效部分的元素与:n表示组n的出现混淆。出于兼容性目的,由于/终止符之前在MASTER_SITE_SUBDIRPATCH_SITE_SUBDIR元素中都不需要,如果紧接在后缀之前的字符不是/,则:n将被视为元素的有效部分,而不是组后缀,即使元素后缀为:n。请参阅MASTER_SITE_SUBDIRMASTER_SITES:n的详细用法使用逗号运算符的MASTER_SITES:n的详细用法

      示例 24. MASTER_SITE_SUBDIRMASTER_SITES:n的详细用法
      MASTER_SITE_SUBDIR=	old:n new/:NEW
      • DEFAULT组中的目录 → old:n

      • NEW组中的目录 → new

      示例 25. 使用逗号运算符、多个文件、多个站点和多个子目录的MASTER_SITES:n的详细用法
      MASTER_SITES=	http://site1/%SUBDIR%/ http://site2/:DEFAULT \
      		http://site3/:group3 http://site4/:group4 \
      		http://site5/:group5 http://site6/:group6 \
      		http://site7/:DEFAULT,group6 \
      		http://site8/%SUBDIR%/:group6,group7 \
      		http://site9/:group8
      DISTFILES=	file1 file2:DEFAULT file3:group3 \
      		file4:group4,group5,group6 file5:grouping \
      		file6:group7
      MASTER_SITE_SUBDIR=	directory-trial:1 directory-n/:groupn \
      		directory-one/:group6,DEFAULT \
      		directory

      前面的示例导致了这种细粒度的获取。站点按其将被使用的确切顺序列出。

  8. 如何对bsd.sites.mk中的一个特殊宏进行分组,例如 SourceForge (SF)?

    示例 26. 使用 SourceForge (SF) 的 MASTER_SITES:n 的详细用法
    MASTER_SITES=	http://site1/ SF/something/1.0:sourceforge,TEST
    DISTFILES=	something.tar.gz:sourceforge

    something.tar.gz 将从 SourceForge 中的所有站点获取。

  9. 如何与PATCH*一起使用?

    所有示例都使用MASTER*完成,但它们对PATCH*也完全适用,如使用PATCH_SITESMASTER_SITES:n简化用法所示。

    示例 27. 使用PATCH_SITESMASTER_SITES:n简化用法
    PATCH_SITES=	http://site1/ http://site2/:test
    PATCHFILES=	patch1:test

5.4.9.3. 端口发生了哪些变化?哪些没有变化?

  1. 所有当前端口保持不变。仅当存在后缀为:n的元素(如前面提到的语法规则中所述的元素,尤其是在项目7中所示)时,才会激活MASTER_SITES:n功能代码。

  2. 端口目标保持不变:checksummakesumpatchconfigurebuild等。do-fetchfetch-listmaster-sitespatch-sites除外。

    • do-fetch:部署新的分组后缀DISTFILESPATCHFILES,以及它们在MASTER_SITESPATCH_SITES中匹配的组元素,这些元素使用MASTER_SITE_SUBDIRPATCH_SITE_SUBDIR中匹配的组元素。请查看使用逗号运算符的MASTER_SITES:n的详细用法

    • fetch-list:与旧的fetch-list类似,区别在于它像do-fetch一样进行分组。

    • master-sitespatch-sites:(与旧版本不兼容)仅返回组DEFAULT的元素;实际上,它们分别执行目标master-sites-defaultpatch-sites-default

      此外,使用目标master-sites-allpatch-sites-all优于直接检查MASTER_SITESPATCH_SITES。此外,在任何将来版本中,都不能保证直接检查有效。请查看项目B以获取有关这些新端口目标的更多信息。

  3. 新的端口目标

    1. master-sites-npatch-sites-n目标,它们将分别列出MASTER_SITESPATCH_SITES中相应组n的元素。例如,master-sites-DEFAULTpatch-sites-DEFAULT将返回组DEFAULT的元素,master-sites-testpatch-sites-test将返回组test的元素,依此类推。

    2. 有新的目标master-sites-allpatch-sites-all,它们执行旧的master-sitespatch-sites目标的工作。它们返回所有组的元素,就像它们都属于同一个组一样,但要注意的是,它会列出与DISTFILESPATCHFILES中定义的组一样多的MASTER_SITE_BACKUPMASTER_SITE_OVERRIDE;分别对应于master-sites-allpatch-sites-all

5.4.10. DIST_SUBDIR

不要让端口弄乱/usr/ports/distfiles。如果端口需要获取大量文件,或包含名称可能与其他端口冲突的文件(例如,Makefile),请将DIST_SUBDIR设置为端口的名称(${PORTNAME}${PKGNAMEPREFIX}${PORTNAME}都可以)。这将把DISTDIR从默认的/usr/ports/distfiles更改为/usr/ports/distfiles/${DIST_SUBDIR},并且实际上将端口所需的所有内容都放入该子目录中。

它还会查看http://distcache.FreeBSD.org上的备份主站点上同名的子目录(在Makefile中显式设置DISTDIR无法实现此目的,因此请使用DIST_SUBDIR)。

这不会影响Makefile中定义的MASTER_SITES

5.5. MAINTAINER

请在此处设置您的邮件地址。拜托。:-)

仅允许单个地址(不包含注释部分)作为MAINTAINER值。使用的格式为[email protected]。请不要包含任何描述性文本,例如真实姓名,此条目中。这只会使端口基础设施和大多数使用它的工具感到困惑。

维护人员负责使端口保持最新并确保其正常工作。有关端口维护人员职责的详细说明,请参阅端口维护人员面临的挑战

维护人员自愿维护端口的良好工作状态。维护人员对其端口负有主要责任,但并非排他所有权。端口是为了社区的利益而存在的,实际上属于社区。这意味着除维护人员以外的人员可以更改端口。对 Ports Collection 的重大更改可能需要更改许多端口。FreeBSD Ports 管理团队或其他团队的成员可能会修改端口以修复依赖项问题或其他问题,例如共享库更新的版本升级。

某些类型的修复已获得 Ports 管理团队<[email protected]>的“全面批准”,允许任何提交者修复任何端口上的这些类别的问 题。这些修复不需要维护人员的批准。

大多数端口的全面批准适用于基础设施更改之类的修复,或者微不足道且经过测试的构建和运行时修复。当前列表可在提交者指南的端口部分找到。

对端口的其他更改将发送给维护者以进行审查和批准,然后再提交。如果维护者在两周内(不包括主要的公共假期)未回复更新请求,则视为维护者超时,并且可以在没有明确维护者批准的情况下进行更新。如果维护者在三个月内未回复,或者如果连续出现三次超时,则该维护者被视为擅离职守,其所有端口都可以分配回池。对此的例外情况是端口管理团队<[email protected]>或安全官员团队<[email protected]>维护的任何内容。绝不允许对这些组维护的端口进行未经授权的提交。

我们保留修改维护者提交内容的权利,以使其更好地符合端口集合的现有策略和风格,而无需提交者或维护者的明确许可。此外,大型基础设施更改可能导致端口在未经维护者同意的情况下被修改。这些类型的更改永远不会影响端口的功能。

端口管理团队<[email protected]>保留出于任何原因撤销或覆盖任何人的维护权的权利,而安全官员团队<[email protected]>保留出于安全原因撤销或覆盖维护权的权利。

5.6. COMMENT

注释是pkg info显示的端口的单行描述。撰写时请遵循以下规则

  1. COMMENT 字符串应为 70 个字符或更少。

  2. 包含软件的包名称或版本号。

  3. 注释必须以大写字母开头,以不带句号结尾。

  4. 不要以不定冠词(即 A 或 An)开头。

  5. 将名称(如 Apache、JavaScript 或 Perl)的首字母大写。

  6. 对于单词列表,使用串行逗号:“绿色、红色和蓝色”。

  7. 检查拼写错误。

以下是一个示例

COMMENT=	Cat chasing a mouse all over the screen

COMMENT 变量紧跟在 Makefile 中的 MAINTAINER 变量之后。

5.7. 项目网站

每个端口都应指向提供有关软件更多信息的网站。

尽可能使用软件开发人员维护的官方项目网站。

WWW=		https://ffmpeg.org/

但它也可以是源代码存储库中的目录或资源

WWW=		https://sourceforge.net/projects/mpd/

WWW 变量紧跟在 Makefile 中的 COMMENT 变量之后。

如果可以通过 HTTP 和 HTTPS 访问相同的内容,则应使用以https://开头的 URL。如果 URI 是网站或目录的根目录,则必须以斜杠结尾。

此信息以前放置在 pkg-descr 文件的最后一行。为了更方便地维护和处理,它已移至 Makefile 中。在 pkg-descr 文件末尾使用WWW:行已弃用。

5.8. 许可证

每个端口都必须记录其可用的许可证。如果它不是 OSI 批准的许可证,则还必须记录任何重新分发限制。

5.8.1. LICENSE

许可证的简称,如果适用多个许可证,则为多个许可证的简称。

如果它是预定义许可证列表中列出的许可证之一,则只能设置LICENSE_FILELICENSE_DISTFILES变量。

如果这是一个在端口框架中未定义的许可证(请参阅预定义许可证列表),则必须设置LICENSE_PERMSLICENSE_NAME,以及LICENSE_FILELICENSE_TEXT。还可以设置LICENSE_DISTFILESLICENSE_GROUPS,但不是必需的。

预定义的许可证显示在预定义许可证列表中。当前列表始终可在 Mk/bsd.licenses.db.mk 中获得。

示例 28. 最简单的用法,预定义许可证

当某些软件的 README 中写着“此软件根据自由软件基金会发布的 GNU 宽通用公共许可证的条款;许可证版本 2.1 或(根据您的选择)任何更高版本。”但未提供许可证文件时,请使用此方法

LICENSE=	LGPL21+

当软件提供许可证文件时,请使用此方法

LICENSE=	LGPL21+
LICENSE_FILE=	${WRKSRC}/COPYING

对于预定义的许可证,默认权限为dist-mirror dist-sell pkg-mirror pkg-sell auto-accept

表 7. 预定义许可证列表
简称名称权限

AGPLv3

GNU Affero 通用公共许可证版本 3

FSF GPL OSI

(默认)

AGPLv3+

GNU Affero 通用公共许可证版本 3(或更高版本)

FSF GPL OSI

(默认)

APACHE10

Apache 许可证 1.0

FSF

(默认)

APACHE11

Apache 许可证 1.1

FSF OSI

(默认)

APACHE20

Apache 许可证 2.0

FSF OSI

(默认)

ART10

Artistic 许可证版本 1.0

OSI

(默认)

ART20

Artistic 许可证版本 2.0

FSF GPL OSI

(默认)

ARTPERL10

Artistic 许可证(perl)版本 1.0

OSI

(默认)

BSD

BSD 许可证通用版本(已弃用)

FSF OSI COPYFREE

(默认)

BSD2CLAUSE

BSD 2 条款“简化”许可证

FSF OSI COPYFREE

(默认)

BSD3CLAUSE

BSD 3 条款“新”或“修订”许可证

FSF OSI COPYFREE

(默认)

BSD4CLAUSE

BSD 4 条款“原始”或“旧”许可证

FSF

(默认)

BSL

Boost 软件许可证

FSF OSI COPYFREE

(默认)

CC-BY-1.0

知识共享署名 1.0

(默认)

CC-BY-2.0

知识共享署名 2.0

(默认)

CC-BY-2.5

知识共享署名 2.5

(默认)

CC-BY-3.0

知识共享署名 3.0

(默认)

CC-BY-4.0

知识共享署名 4.0

(默认)

CC-BY-NC-1.0

知识共享署名-非商业性使用 1.0

dist-mirrorpkg-mirrorauto-accept

CC-BY-NC-2.0

知识共享署名-非商业性使用 2.0

dist-mirrorpkg-mirrorauto-accept

CC-BY-NC-2.5

知识共享署名-非商业性使用 2.5

dist-mirrorpkg-mirrorauto-accept

CC-BY-NC-3.0

知识共享署名-非商业性使用 3.0

dist-mirrorpkg-mirrorauto-accept

CC-BY-NC-4.0

知识共享署名-非商业性使用 4.0

dist-mirrorpkg-mirrorauto-accept

CC-BY-NC-ND-1.0

知识共享署名-非商业性使用-禁止演绎 1.0

dist-mirrorpkg-mirrorauto-accept

CC-BY-NC-ND-2.0

知识共享署名-非商业性使用-禁止演绎 2.0

dist-mirrorpkg-mirrorauto-accept

CC-BY-NC-ND-2.5

知识共享署名-非商业性使用-禁止演绎 2.5

dist-mirrorpkg-mirrorauto-accept

CC-BY-NC-ND-3.0

知识共享署名-非商业性使用-禁止演绎 3.0

dist-mirrorpkg-mirrorauto-accept

CC-BY-NC-ND-4.0

知识共享署名-非商业性使用-禁止演绎 4.0

dist-mirrorpkg-mirrorauto-accept

CC-BY-NC-SA-1.0

知识共享署名-非商业性使用-相同方式共享 1.0

dist-mirrorpkg-mirrorauto-accept

CC-BY-NC-SA-2.0

知识共享署名-非商业性使用-相同方式共享 2.0

dist-mirrorpkg-mirrorauto-accept

CC-BY-NC-SA-2.5

知识共享署名-非商业性使用-相同方式共享 2.5

dist-mirrorpkg-mirrorauto-accept

CC-BY-NC-SA-3.0

知识共享署名-非商业性使用-相同方式共享 3.0

dist-mirrorpkg-mirrorauto-accept

CC-BY-NC-SA-4.0

知识共享署名-非商业性使用-相同方式共享 4.0

dist-mirrorpkg-mirrorauto-accept

CC-BY-ND-1.0

知识共享署名-禁止演绎 1.0

(默认)

CC-BY-ND-2.0

知识共享署名-禁止演绎 2.0

(默认)

CC-BY-ND-2.5

知识共享署名-禁止演绎 2.5

(默认)

CC-BY-ND-3.0

知识共享署名-禁止演绎 3.0

(默认)

CC-BY-ND-4.0

知识共享署名-禁止演绎 4.0

(默认)

CC-BY-SA-1.0

知识共享署名-相同方式共享 1.0

(默认)

CC-BY-SA-2.0

知识共享署名-相同方式共享 2.0

(默认)

CC-BY-SA-2.5

知识共享署名-相同方式共享 2.5

(默认)

CC-BY-SA-3.0

知识共享署名-相同方式共享 3.0

(默认)

CC-BY-SA-4.0

知识共享署名-相同方式共享 4.0

(默认)

CC0-1.0

知识共享零版 1.0 通用版

FSF GPL COPYFREE

(默认)

CDDL

通用开发和分发许可证

FSF OSI

(默认)

CPAL-1.0

通用公共署名许可证

FSF OSI

(默认)

ClArtistic

澄清的 Artistic 许可证

FSF GPL OSI

(默认)

EPL

Eclipse 公共许可证

FSF OSI

(默认)

GFDL

GNU 自由文档许可证

FSF

(默认)

GMGPL

GNAT 修改后的通用公共许可证

FSF GPL OSI

(默认)

GPLv1

GNU 通用公共许可证版本 1

FSF GPL OSI

(默认)

GPLv1+

GNU 通用公共许可证版本 1(或更高版本)

FSF GPL OSI

(默认)

GPLv2

GNU 通用公共许可证版本 2

FSF GPL OSI

(默认)

GPLv2+

GNU 通用公共许可证版本 2(或更高版本)

FSF GPL OSI

(默认)

GPLv3

GNU 通用公共许可证版本 3

FSF GPL OSI

(默认)

GPLv3+

GNU 通用公共许可证版本 3(或更高版本)

FSF GPL OSI

(默认)

GPLv3RLE

GNU GPL 版本 3 运行时库例外

FSF GPL OSI

(默认)

GPLv3RLE+

GNU GPL 版本 3 运行时库例外(或更高版本)

FSF GPL OSI

(默认)

ISCL

互联网系统联盟许可证

FSF GPL OSI COPYFREE

(默认)

LGPL20

GNU 库通用公共许可证版本 2.0

FSF GPL OSI

(默认)

LGPL20+

GNU 库通用公共许可证版本 2.0(或更高版本)

FSF GPL OSI

(默认)

LGPL21

GNU 宽通用公共许可证版本 2.1

FSF GPL OSI

(默认)

LGPL21+

GNU 宽通用公共许可证版本 2.1(或更高版本)

FSF GPL OSI

(默认)

LGPL3

GNU 宽通用公共许可证版本 3

FSF GPL OSI

(默认)

LGPL3+

GNU 宽通用公共许可证版本 3(或更高版本)

FSF GPL OSI

(默认)

LPPL10

LaTeX 项目公共许可证版本 1.0

FSF OSI

dist-mirror dist-sell

LPPL11

LaTeX 项目公共许可证版本 1.1

FSF OSI

dist-mirror dist-sell

LPPL12

LaTeX 项目公共许可证版本 1.2

FSF OSI

dist-mirror dist-sell

LPPL13

LaTeX 项目公共许可证版本 1.3

FSF OSI

dist-mirror dist-sell

LPPL13a

LaTeX 项目公共许可证版本 1.3a

FSF OSI

dist-mirror dist-sell

LPPL13b

LaTeX 项目公共许可证版本 1.3b

FSF OSI

dist-mirror dist-sell

LPPL13c

LaTeX 项目公共许可证版本 1.3c

FSF OSI

dist-mirror dist-sell

MIT

MIT 许可证/X11 许可证

COPYFREE FSF GPL OSI

(默认)

MPL10

Mozilla 公共许可证版本 1.0

FSF OSI

(默认)

MPL11

Mozilla 公共许可证版本 1.1

FSF OSI

(默认)

MPL20

Mozilla 公共许可证版本 2.0

FSF OSI

(默认)

NCSA

伊利诺伊大学/NCSA 开源许可证

COPYFREE FSF GPL OSI

(默认)

NONE

未指定许可证

OFL10

SIL 开放字体许可证版本 1.0 (https://scripts.sil.org/OFL/)

FONTS

(默认)

OFL11

SIL 开放字体许可证版本 1.1 (https://scripts.sil.org/OFL/)

FONTS

(默认)

OWL

开放作品许可证 (owl.apotheon.org)

COPYFREE

(默认)

OpenSSL

OpenSSL 许可证

FSF

(默认)

PD

公共领域

GPL COPYFREE

(默认)

PHP202

PHP 许可证版本 2.02

FSF OSI

(默认)

PHP30

PHP 许可证版本 3.0

FSF OSI

(默认)

PHP301

PHP 许可证版本 3.01

FSF OSI

(默认)

PSFL

Python 软件基金会许可证

FSF GPL OSI

(默认)

PostgreSQL

PostgreSQL 许可证

FSF GPL OSI COPYFREE

(默认)

RUBY

Ruby 许可证

FSF

(默认)

UNLICENSE

Unlicense

COPYFREE FSF GPL

(默认)

WTFPL

随心所欲公共许可证版本 2

GPL FSF COPYFREE

(默认)

WTFPL1

随心所欲公共许可证版本 1

GPL FSF COPYFREE

(默认)

ZLIB

zlib 许可证

GPL FSF OSI

(默认)

ZPL21

Zope 公共许可证版本 2.1

GPL OSI

(默认)

5.8.2. LICENSE_PERMSLICENSE_PERMS_NAME_

权限。如果为空,则使用 none

许可证权限列表
dist-mirror

允许重新分发发行版文件。发行版文件将添加到 FreeBSD 的 MASTER_SITE_BACKUP CDN 中。

no-dist-mirror

禁止重新分发发行版文件。这等同于设置 RESTRICTED。发行版文件不会添加到 FreeBSD 的 MASTER_SITE_BACKUP CDN 中。

dist-sell

允许出售发行版文件。发行版文件将出现在安装程序镜像中。

no-dist-sell

禁止出售发行版文件。这等同于设置 NO_CDROM

pkg-mirror

允许免费重新分发软件包。该软件包将在 FreeBSD 软件包 CDN https://pkg.freebsd.org/ 上分发。

no-pkg-mirror

禁止免费重新分发软件包。等同于设置 NO_PACKAGE。该软件包不会从 FreeBSD 软件包 CDN https://pkg.freebsd.org/ 分发。

pkg-sell

允许出售软件包。该软件包将出现在安装程序镜像中。

no-pkg-sell

禁止出售软件包。这等同于设置 NO_CDROM。该软件包不会出现在安装程序镜像中。

auto-accept

默认接受许可证。除非用户已定义 LICENSES_ASK,否则不会显示接受许可证的提示。除非许可证规定用户必须接受许可证条款,否则请使用此选项。

no-auto-accept

默认不接受许可证。系统将始终要求用户确认接受此许可证。如果许可证规定用户必须接受其条款,则必须使用此选项。

当同时存在 permissionno-permission 时,no-permission 将取消 permission

permission 不存在时,则将其视为 no-permission

某些缺少的权限将阻止软件包用户使用端口(以及所有依赖它的端口)。

没有 auto-accept 权限的端口将永远不会被构建,并且所有依赖它的端口都将被忽略。

没有 pkg-mirror 权限的端口将在构建后被删除,以及所有依赖它的端口,并且它们永远不会被分发。

示例 29. 非标准许可证

阅读许可证条款,并使用可用的权限进行翻译。

LICENSE=        UNKNOWN
LICENSE_NAME=   unknown
LICENSE_TEXT=   This program is NOT in public domain.\
                It can be freely distributed for non-commercial purposes only.
LICENSE_PERMS=  dist-mirror no-dist-sell pkg-mirror no-pkg-sell auto-accept
示例 30. 标准和非标准许可证

阅读许可证条款,并使用可用的权限表达这些条款。如有疑问,请在 FreeBSD 端口邮件列表 中寻求指导。

LICENSE=        WARSOW GPLv2
LICENSE_COMB=   multi
LICENSE_NAME_WARSOW=    Warsow Content License
LICENSE_FILE_WARSOW=    ${WRKSRC}/docs/license.txt
LICENSE_PERMS_WARSOW=   dist-mirror pkg-mirror auto-accept

当 GPLv2 和 UNKNOWN 许可证的权限混合时,端口最终将具有 dist-mirror dist-sell pkg-mirror pkg-sell auto-accept dist-mirror no-dist-sell pkg-mirror no-pkg-sell auto-acceptno-permissions 取消 permissions。生成的权限列表为 dist-mirror pkg-mirror auto-accept。发行版文件和软件包将不会在安装程序镜像中提供。

5.8.3. LICENSE_GROUPSLICENSE_GROUPS_NAME

许可证所属的组。

预定义许可证组列表
FSF

自由软件基金会批准,请参阅 FSF 许可和合规团队

GPL

GPL 兼容

OSI

OSI 批准,请参阅开源计划 开源许可证 页面。

COPYFREE

符合免复制标准定义,请参阅 免复制许可证 页面。

FONTS

字体许可证

5.8.4. LICENSE_NAMELICENSE_NAME_NAME

许可证的全称。

示例 31. LICENSE_NAME
LICENSE=        UNRAR
LICENSE_NAME=   UnRAR License
LICENSE_FILE=   ${WRKSRC}/license.txt
LICENSE_PERMS=  dist-mirror dist-sell pkg-mirror pkg-sell auto-accept

5.8.5. LICENSE_FILELICENSE_FILE_NAME

包含许可证文本的文件的完整路径,通常为 ${WRKSRC}/some/file。如果文件不在 distfile 中,并且其内容过长而无法放入 LICENSE_TEXT 中,请将其放入 ${FILESDIR} 中的新文件中。

示例 32. LICENSE_FILE
LICENSE=	GPLv3+
LICENSE_FILE=	${WRKSRC}/COPYING

5.8.6. LICENSE_TEXTLICENSE_TEXT_NAME

用作许可证的文本。当许可证不在分发文件中且其文本较短时很有用。

示例 33. LICENSE_TEXT
LICENSE=        UNKNOWN
LICENSE_NAME=   unknown
LICENSE_TEXT=   This program is NOT in public domain.\
                It can be freely distributed for non-commercial purposes only,\
                and THERE IS NO WARRANTY FOR THIS PROGRAM.
LICENSE_PERMS=  dist-mirror no-dist-sell pkg-mirror no-pkg-sell auto-accept

5.8.7. LICENSE_DISTFILESLICENSE_DISTFILES_NAME

许可证适用的分发文件。默认为所有分发文件。

示例 34. LICENSE_DISTFILES

当分发文件不都具有相同的许可证时使用。例如,一个具有代码许可证,另一个具有某些无法重新分发的艺术作品。

MASTER_SITES=   SF/some-game
DISTFILES=      ${DISTNAME}${EXTRACT_SUFX} artwork.zip

LICENSE=        BSD3CLAUSE ARTWORK
LICENSE_COMB=   dual
LICENSE_NAME_ARTWORK=      The game artwork license
LICENSE_TEXT_ARTWORK=      The README says that the files cannot be redistributed
LICENSE_PERMS_ARTWORK=     pkg-mirror pkg-sell auto-accept
LICENSE_DISTFILES_BSD3CLAUSE=   ${DISTNAME}${EXTRACT_SUFX}
LICENSE_DISTFILES_ARTWORK= artwork.zip

5.8.8. LICENSE_COMB

如果所有许可证都适用,则设置为 multi。如果任何许可证都适用,则设置为 dual。默认为 single

示例 35. 双重许可证

当端口说明“此软件可以在 GNU 通用公共许可证或 Artistic 许可证下分发”时,表示可以使用任一许可证。使用此选项。

LICENSE=	ART10 GPLv1
LICENSE_COMB=   dual

如果提供了许可证文件,请使用此选项。

LICENSE=	ART10 GPLv1
LICENSE_COMB=   dual
LICENSE_FILE_ART10=     ${WRKSRC}/Artistic
LICENSE_FILE_GPLv1=     ${WRKSRC}/Copying
示例 36. 多个许可证

当端口的一部分具有一个许可证,而另一部分具有不同的许可证时,请使用 multi

LICENSE=	GPLv2 LGPL21+
LICENSE_COMB=	multi

5.9. PORTSCOUT

Portscout 是 FreeBSD 端口集合的自动化 distfile 检查实用程序,在 Portscout:FreeBSD 端口 Distfile 扫描程序 中详细描述。

PORTSCOUT 定义了 Portscout distfile 扫描程序受限的特殊条件。

设置 PORTSCOUT 的情况包括

  • 当必须忽略特定版本的 distfile 时。例如,要从 distfile 版本检查中排除版本8.2和版本8.3,因为已知它们已损坏,请添加

    PORTSCOUT=	skipv:8.2,8.3
  • 当必须完全禁用 distfile 版本检查时。例如,如果端口将永远不再更新,请添加

    PORTSCOUT=	ignore:1
  • 当必须检查 distfile 的特定版本或特定主版本和次版本时。例如,如果只需要监视版本0.6.4,因为较新版本与 FreeBSD 不兼容,请添加

    PORTSCOUT=	limit:^0\.6\.4
  • 当列出可用版本的 URL 与下载 URL 不同时。例如,要将 distfile 版本检查限制在 databases/pgtune 端口的下载页面,请添加

    PORTSCOUT=	site:http://www.renpy.org/dl/release/

5.10. 依赖项

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

当软件具有提供额外功能的额外依赖项时,*_DEPENDS 中列出的基本依赖项应包含最有利于大多数用户的额外依赖项。基本依赖项绝不应该是“最小”依赖项集。目标不是包含所有可能的依赖项。仅包含最有利于大多数人的依赖项。

5.10.1. LIB_DEPENDS

此变量指定此端口依赖的共享库。它是一个 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

此变量指定此端口在运行时依赖的可执行文件或文件。它是一个 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 实际上是一个可执行文件;如果可执行文件位于搜索路径中预期之外的位置,请使用完整路径名。

端口构建集群上使用的官方搜索 PATH

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

依赖项在 install 目标内检查。此外,依赖项的名称将放入软件包中,以便 pkg install(请参阅 pkg-install(8))如果它不在用户的系统上,将自动安装它。如果 targetDEPENDS_TARGET 相同,则可以省略 target 部分。

一个非常常见的情况是RUN_DEPENDSBUILD_DEPENDS完全相同,尤其是在移植的软件是用脚本语言编写的或需要相同的构建和运行时环境时。在这种情况下,直接将其中一个赋值给另一个既诱人又直观。

RUN_DEPENDS=	${BUILD_DEPENDS}

但是,这种赋值可能会用端口原始BUILD_DEPENDS中未定义的条目污染运行时依赖项。这是因为make(1)对变量赋值进行了延迟求值。考虑一个包含USE_*Makefile,它由ports/Mk/bsd.*.mk处理以增加初始构建依赖项。例如,USES= gmakedevel/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

此变量指定此端口构建所需的执行文件或文件。与RUN_DEPENDS类似,它是一个path:dir[:target]元组列表。例如,

BUILD_DEPENDS=	unzip:archivers/unzip

将检查名为unzip的可执行文件,并进入端口树的archivers/unzip子目录以构建和安装它(如果未找到)。

这里的“构建”是指从提取到编译的所有过程。依赖项在extract目标内进行检查。如果targetDEPENDS_TARGET相同,则可以省略target部分。

5.10.4. FETCH_DEPENDS

此变量指定此端口获取所需的执行文件或文件。与前两个类似,它是一个path:dir[:target]元组列表。例如,

FETCH_DEPENDS=	ncftp2:net/ncftp2

将检查名为ncftp2的可执行文件,并进入端口树的net/ncftp2子目录以构建和安装它(如果未找到)。

依赖项在fetch目标内进行检查。如果targetDEPENDS_TARGET相同,则可以省略target部分。

5.10.5. EXTRACT_DEPENDS

此变量指定此端口提取所需的执行文件或文件。与前面的类似,它是一个path:dir[:target]元组列表。例如,

EXTRACT_DEPENDS=	unzip:archivers/unzip

将检查名为unzip的可执行文件,并进入端口树的archivers/unzip子目录以构建和安装它(如果未找到)。

依赖项在extract目标内进行检查。如果targetDEPENDS_TARGET相同,则可以省略target部分。

仅当提取不起作用(默认情况下假设使用tar)且无法使用使用USES中描述的USES=tarUSES=lhaUSES=zip使其工作时,才使用此变量。

5.10.6. PATCH_DEPENDS

此变量指定此端口修补所需的执行文件或文件。与前面的类似,它是一个path:dir[:target]元组列表。例如,

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

将进入端口树的java/jfc子目录以提取它。

依赖项在patch目标内进行检查。如果targetDEPENDS_TARGET相同,则可以省略target部分。

5.10.7. USES

可以添加参数来定义端口使用的不同功能和依赖项。它们通过在Makefile中添加此行来指定

USES= feature[:arguments]

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

在包含bsd.port.pre.mk之后,不能分配USES

5.10.8. USE_*

存在多个变量来定义许多端口共享的常用依赖项。它们的使用是可选的,但有助于减少端口Makefile的冗长性。它们中的每一个都以USE_*样式命名。这些变量只能在端口Makefileports/Mk/bsd.*.mk中使用。它们不适用于用户可设置的选项 - 请为此目的使用PORT_OPTIONS

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

USE_GCC=X.Y

(其中X.Y是版本号)会为每个端口添加对gccXY的依赖关系,包括lang/gccXY本身!

表 8. USE_*
变量含义

USE_GCC

端口需要GCC(gccg++)来构建。某些端口需要特定的旧版GCC版本,某些端口需要现代的最新版本。它通常设置为yes(表示始终使用来自端口的稳定、现代的GCC,根据Mk/bsd.default-versions.mk中的GCC_DEFAULT)。这也是默认值。还可以指定确切的版本,例如值10。当GCC来自基础系统并且满足请求的版本时,将使用它,否则将从端口构建合适的编译器,并相应地调整CCCXX。版本规范符后面的:build参数仅向端口添加构建时依赖项。

例如

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已弃用,不应在新端口中使用。

与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. 依赖项的最小版本

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

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

第一个字段包含一个依赖包名称,该名称必须与包数据库中的条目匹配,一个比较符号和一个包版本。如果安装了p5-Spiffy-0.26或更高版本,则满足依赖关系。

5.10.10. 关于依赖项的说明

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

运行make clean时,端口依赖项也会自动清理。如果不需要这样做,请在环境中定义NOCLEANDEPENDS。如果端口的依赖项列表中包含需要很长时间才能重建的内容(例如KDE、GNOME或Mozilla),则这可能特别有用。

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

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

将始终进入jpeg端口并提取它。

5.10.11. 循环依赖关系是致命的

不要在端口树中引入任何循环依赖关系!

端口构建技术无法容忍循环依赖关系。如果引入了一个循环依赖关系,那么世界上某个人、某个地方的FreeBSD安装几乎会立即被破坏,并且很快就会有更多人受到影响。这些确实很难检测到。如有疑问,在进行更改之前,请确保运行:cd /usr/ports; make index。在较旧的机器上,此过程可能非常慢,但它可以帮助大量人(包括您自己)避免很多麻烦。

5.10.12. 自动依赖关系引起的问题

必须显式声明依赖项,或者使用OPTIONS框架声明依赖项。使用其他方法(如自动检测)会使索引复杂化,从而导致端口和包管理出现问题。

示例 37. 可选依赖项的错误声明
.include <bsd.port.pre.mk>

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

尝试自动添加依赖项的问题在于,单个端口之外的文件和设置随时可能发生更改。例如:构建索引,然后安装一批端口。但是其中一个端口安装了测试文件。索引现在不正确,因为已安装的端口意外地具有新的依赖项。即使在重建后,索引也可能仍然不正确,如果其他端口也根据其他文件的存在来确定其对依赖项的需求。

示例 38. 可选依赖项的正确声明
OPTIONS_DEFINE=	BAR
BAR_DESC=	Calling cellphones via bar

BAR_LIB_DEPENDS=	libbar.so:foo/bar

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

5.11. 从属端口和MASTERDIR

如果端口需要通过让变量(例如分辨率或纸张尺寸)取不同的值来构建略微不同的软件包版本,请为每个软件包创建一个子目录,以便用户更容易查看该怎么做,但尝试在端口之间共享尽可能多的文件。通常,通过巧妙地使用变量,除了一个目录之外,所有目录中只需要一个非常简短的Makefile。在唯一的Makefile中,使用MASTERDIR指定其余文件所在的目录。此外,将变量用作PKGNAMESUFFIX的一部分,以便软件包具有不同的名称。

这将通过一个示例得到最好的证明。这是print/pkfonts300/Makefile的一部分;

PORTNAME=	pkfonts${RESOLUTION}
PORTVERSION=	1.0
DISTFILES=	pk${RESOLUTION}.tar.gz

PLIST=		${PKGDIR}/pkg-plist.${RESOLUTION}

.if !defined(RESOLUTION)
RESOLUTION=	300
.else
.if ${RESOLUTION} != 118 && ${RESOLUTION} != 240 && \
	${RESOLUTION} != 300 && ${RESOLUTION} != 360 && \
	${RESOLUTION} != 400 && ${RESOLUTION} != 600
.BEGIN:
	@${ECHO_MSG} "Error: invalid value for RESOLUTION: \"${RESOLUTION}\""
	@${ECHO_MSG} "Possible values are: 118, 240, 300, 360, 400 and 600."
	@${FALSE}
.endif
.endif

print/pkfonts300还具有所有常规补丁、包文件等。在那里运行make,它将采用分辨率的默认值(300)并正常构建端口。

至于其他分辨率,这是整个print/pkfonts360/Makefile

RESOLUTION=	360
MASTERDIR=	${.CURDIR}/../pkfonts300

.include	"${MASTERDIR}/Makefile"

print/pkfonts118/Makefileprint/pkfonts600/Makefile以及所有其他文件都类似)。MASTERDIR定义告诉bsd.port.mk,像FILESDIRSCRIPTDIR这样的常规子目录集位于pkfonts300下。RESOLUTION=360行将覆盖pkfonts300/Makefile中的RESOLUTION=300行,并且端口将以设置为360的分辨率构建。

5.12. 手册页

如果端口将其手册树锚定在PREFIX以外的其他位置,请使用MANDIRS指定这些目录。请注意,与手册页对应的文件必须与其余文件一起放置在pkg-plist中。MANDIRS的目的是启用手册页的自动压缩,因此文件名以.gz为后缀。

5.13. Info 文件

如果软件包需要安装GNU info文件,请在INFO中列出它们(不带尾随的.info),每个文档一个条目。假定这些文件安装到PREFIX/INFO_PATH。如果软件包使用其他位置,请更改INFO_PATH。但是,不建议这样做。这些条目仅包含相对于PREFIX/INFO_PATH的路径。例如,lang/gcc34将info文件安装到PREFIX/INFO_PATH/gcc34,而INFO将如下所示

INFO=	gcc34/cpp gcc34/cppinternals gcc34/g77 ...

适当的安装/卸载代码将在软件包注册之前自动添加到临时pkg-plist中。

5.14. Makefile 选项

许多应用程序可以使用可选或不同的配置进行构建。例如,选择自然(人类)语言、GUI与命令行,或要支持的数据库类型。用户可能需要与默认配置不同的配置,因此端口系统提供了端口作者可用于控制将构建哪个变体的钩子。正确支持这些选项将使用户满意,并有效地以一个端口的价格提供两个或多个端口。

5.14.1. OPTIONS

5.14.1.1. 背景

OPTIONS_*为安装端口的用户提供一个显示可用选项的对话框,然后将这些选项保存到${PORT_DBDIR}/${OPTIONS_NAME}/options。下次构建端口时,将重用这些选项。PORT_DBDIR默认为/var/db/portsOPTIONS_NAME为端口来源,以下划线作为空格分隔符,例如,对于dns/bind99,它将是dns_bind99

当用户运行make config(或第一次运行make build)时,框架会检查${PORT_DBDIR}/${OPTIONS_NAME}/options。如果该文件不存在,则使用OPTIONS_*的值,并显示一个对话框,用户可以在其中启用或禁用选项。然后保存options,并在构建端口时使用配置的变量。

如果端口的新版本添加了新的OPTIONS,则会向用户显示对话框,并预填充旧OPTIONS的保存值。

make showconfig显示保存的配置。使用make rmconfig删除保存的配置。

5.14.1.2. 语法

OPTIONS_DEFINE包含要使用的OPTIONS列表。这些是相互独立的,并且没有分组

OPTIONS_DEFINE=	OPT1 OPT2

定义后,将描述OPTIONS(可选,但强烈建议)

OPT1_DESC=	Describe OPT1
OPT2_DESC=	Describe OPT2
OPT3_DESC=	Describe OPT3
OPT4_DESC=	Describe OPT4
OPT5_DESC=	Describe OPT5
OPT6_DESC=	Describe OPT6

ports/Mk/bsd.options.desc.mk包含许多常用OPTIONS的描述。虽然通常很有用,但如果描述不足以满足端口的要求,请覆盖它们。

在描述选项时,请从用户的角度来看:“它更改了什么功能?”和“为什么我要启用它?”不要只是重复名称。例如,将NLS选项描述为“包含NLS支持”对用户没有帮助,用户已经可以看到选项名称,但可能不知道它的含义。将其描述为“通过gettext实用程序实现的本地语言支持”更有帮助。

选项名称始终全部大写。它们不能使用混合大小写或小写。

OPTIONS可以分组为单选选项,每个组只能选择一个选项

OPTIONS_SINGLE=		SG1
OPTIONS_SINGLE_SG1=	OPT3 OPT4

每个OPTIONS_SINGLE组都必须始终选择一个,才能使选项有效。每个组的一个选项必须添加到OPTIONS_DEFAULT中。

OPTIONS可以分组为单选选项,每个组可以选择零个或一个选项

OPTIONS_RADIO=		RG1
OPTIONS_RADIO_RG1=	OPT7 OPT8

OPTIONS还可以分组为“多选”列表,其中必须启用至少一个选项

OPTIONS_MULTI=		MG1
OPTIONS_MULTI_MG1=	OPT5 OPT6

OPTIONS还可以分组为“多选”列表,其中可以启用零个或任意选项

OPTIONS_GROUP=		GG1
OPTIONS_GROUP_GG1=	OPT9 OPT10

OPTIONS默认情况下未设置,除非它们列在OPTIONS_DEFAULT

OPTIONS_DEFAULT=	OPT1 OPT3 OPT6

OPTIONS定义必须出现在包含bsd.port.options.mk之前。只有在包含bsd.port.options.mk之后才能测试PORT_OPTIONS值。也可以使用包含bsd.port.pre.mk,并且在引入bsd.port.options.mk之前编写的端口中仍然广泛使用。但请注意,包含bsd.port.pre.mk后,某些变量将无法按预期工作,通常是一些USE_*标志。

示例39. OPTIONS的简单用法
OPTIONS_DEFINE=	FOO BAR
OPTIONS_DEFAULT=FOO

FOO_DESC=	Option foo support
BAR_DESC=	Feature bar support

# Will add --with-foo / --without-foo
FOO_CONFIGURE_WITH=	foo
BAR_RUN_DEPENDS=	bar:bar/bar

.include <bsd.port.mk>
示例40. 检查未设置的端口OPTIONS
.if ! ${PORT_OPTIONS:MEXAMPLES}
CONFIGURE_ARGS+=--without-examples
.endif

上面显示的表单不建议使用。首选方法是使用配置旋钮真正启用和禁用该功能以匹配选项

# Will add --with-examples / --without-examples
EXAMPLES_CONFIGURE_WITH=	examples
示例41. OPTIONS的实际用法
OPTIONS_DEFINE=		EXAMPLES
OPTIONS_DEFAULT=	PGSQL LDAP SSL

OPTIONS_SINGLE=		BACKEND
OPTIONS_SINGLE_BACKEND=	MYSQL PGSQL BDB

OPTIONS_MULTI=		AUTH
OPTIONS_MULTI_AUTH=	LDAP PAM SSL

EXAMPLES_DESC=		Install extra examples
MYSQL_DESC=		Use MySQL as backend
PGSQL_DESC=		Use PostgreSQL as backend
BDB_DESC=		Use Berkeley DB as backend
LDAP_DESC=		Build with LDAP authentication support
PAM_DESC=		Build with PAM support
SSL_DESC=		Build with OpenSSL support

# Will add USE_PGSQL=yes
PGSQL_USE=	pgsql=yes
# Will add --enable-postgres / --disable-postgres
PGSQL_CONFIGURE_ENABLE=	postgres

ICU_LIB_DEPENDS=	libicuuc.so:devel/icu

# Will add --with-examples / --without-examples
EXAMPLES_CONFIGURE_WITH=	examples

# Check other OPTIONS

.include <bsd.port.mk>

5.14.1.3. 默认选项

这些选项默认始终处于启用状态。

  • DOCS - 构建和安装文档。

  • NLS - 本地语言支持。

  • EXAMPLES - 构建和安装示例。

  • IPV6 - IPv6协议支持。

无需将这些添加到OPTIONS_DEFAULT中。但是,要使它们处于活动状态并在选项选择对话框中显示,必须将它们添加到OPTIONS_DEFINE中。

5.14.2. 功能自动激活

使用GNU配置脚本时,请注意哪些可选功能由自动检测激活。通过在CONFIGURE_ARGS中添加--without-xxx--disable-xxx来显式禁用不需要的可选功能。

示例42. 选项的错误处理
.if ${PORT_OPTIONS:MFOO}
LIB_DEPENDS+=		libfoo.so:devel/foo
CONFIGURE_ARGS+=	--enable-foo
.endif

在上面的示例中,假设系统上安装了一个库libfoo。用户不希望此应用程序使用libfoo,因此他在make config对话框中将其关闭。但是,应用程序的配置脚本检测到系统中存在该库,并在生成的执行文件中包含其支持。现在,当用户决定从系统中删除libfoo时,端口系统不会提出异议(没有记录对libfoo的依赖关系),但应用程序会崩溃。

示例43. 选项的正确处理
FOO_LIB_DEPENDS=		libfoo.so:devel/foo
# Will add --enable-foo / --disable-foo
FOO_CONFIGURE_ENABLE=	foo

在某些情况下,简写条件语法会导致复杂结构出现问题。错误通常是Malformed conditional,可以使用替代语法。

.if !empty(VARIABLE:MVALUE)

作为替代

.if ${VARIABLE:MVALUE}

5.14.3. 选项助手

有一些宏可以帮助简化基于设置选项而不同的条件值。为了方便访问,提供了一个完整的列表

PLIST_SUBSUB_LIST

有关自动%%OPT%%%%NOOPT%%生成,请参阅OPTIONS_SUB

有关更复杂的用法,请参阅通用变量替换

CONFIGURE_ARGS

有关--enable-x--disable-x,请参阅OPT_CONFIGURE_ENABLE

有关--with-x--without-x,请参阅OPT_CONFIGURE_WITH

对于所有其他情况,请参阅OPT_CONFIGURE_ONOPT_CONFIGURE_OFF

CMAKE_ARGS

对于布尔值(onofftruefalse01)的参数,请参阅OPT_CMAKE_BOOLOPT_CMAKE_BOOL_OFF

对于所有其他情况,请参阅OPT_CMAKE_ONOPT_CMAKE_OFF

MESON_ARGS

对于采用truefalse的参数,请参阅OPT_MESON_TRUEOPT_MESON_FALSE

对于采用yesno的参数,请使用OPT_MESON_YESOPT_MESON_NO

对于采用enableddisabled的参数,请参阅OPT_MESON_ENABLEDOPT_MESON_DISABLED

对于所有其他情况,请使用OPT_MESON_ONOPT_MESON_OFF

QMAKE_ARGS

请参阅OPT_QMAKE_ONOPT_QMAKE_OFF

USE_*

请参阅OPT_USEOPT_USE_OFF

*_DEPENDS

请参阅依赖项

*(任何变量)

最常用的变量具有直接助手,请参阅通用变量替换

对于任何没有特定助手的变量,请参阅OPT_VARSOPT_VARS_OFF

选项依赖项

当一个选项需要另一个选项才能工作时,请参阅OPT_IMPLIES

选项冲突

当一个选项在另一个选项也启用的情况下无法工作时,请参阅OPT_PREVENTSOPT_PREVENTS_MSG

构建目标

当一个选项需要一些额外的处理时,请参阅其他构建目标

5.14.3.1. OPTIONS_SUB

如果OPTIONS_SUB设置为yes,则添加到OPTIONS_DEFINE的每个选项都将添加到PLIST_SUBSUB_LIST中,例如

OPTIONS_DEFINE=	OPT1
OPTIONS_SUB=	yes

等效于

OPTIONS_DEFINE=	OPT1

.include <bsd.port.options.mk>

.if ${PORT_OPTIONS:MOPT1}
PLIST_SUB+=	OPT1="" NO_OPT1="@comment "
SUB_LIST+=	OPT1="" NO_OPT1="@comment "
.else
PLIST_SUB+=	OPT1="@comment " NO_OPT1=""
SUB_LIST+=	OPT1="@comment " NO_OPT1=""
.endif

OPTIONS_SUB的值会被忽略。将其设置为任何值都会为所有选项添加PLIST_SUBSUB_LIST条目。

5.14.3.2. OPT_USEOPT_USE_OFF

当选择选项OPT时,对于OPT_USE中的每个key=value对,value将附加到相应的USE_KEY。如果value中包含空格,则将其替换为逗号,并在处理过程中将其更改回空格。OPT_USE_OFF的工作方式相同,但当选择OPT时。例如

OPTIONS_DEFINE=	OPT1
OPT1_USES=	xorg
OPT1_USE=	mysql=yes xorg=x11,xextproto,xext,xrandr
OPT1_USE_OFF=	openssl=yes

等效于

OPTIONS_DEFINE=	OPT1

.include <bsd.port.options.mk>

.if ${PORT_OPTIONS:MOPT1}
USE_MYSQL=	yes
USES+=		xorg
USE_XORG=	x11 xextproto xext xrandr
.else
USE_OPENSSL=	yes
.endif

5.14.3.3. CONFIGURE_ARGS 辅助函数

5.14.3.3.1. OPT_CONFIGURE_ENABLE

当选择选项OPT时,对于OPT_CONFIGURE_ENABLE中的每个entry--enable-entry将附加到CONFIGURE_ARGS。当选择选项OPT时,--disable-entry将附加到CONFIGURE_ARGS。可以使用=符号指定可选参数。此参数仅附加到--enable-entry配置选项。例如

OPTIONS_DEFINE=	OPT1 OPT2
OPT1_CONFIGURE_ENABLE=	test1 test2
OPT2_CONFIGURE_ENABLE=	test2=exhaustive

等效于

OPTIONS_DEFINE=	OPT1

.include <bsd.port.options.mk>

.if ${PORT_OPTIONS:MOPT1}
CONFIGURE_ARGS+=	--enable-test1 --enable-test2
.else
CONFIGURE_ARGS+=	--disable-test1 --disable-test2
.endif

.if ${PORT_OPTIONS:MOPT2}
CONFIGURE_ARGS+=	--enable-test2=exhaustive
.else
CONFIGURE_ARGS+=	--disable-test2
.endif
5.14.3.3.2. OPT_CONFIGURE_WITH

当选择选项OPT时,对于OPT_CONFIGURE_WITH中的每个entry--with-_entry将附加到CONFIGURE_ARGS。当选择选项OPT时,--without-entry将附加到CONFIGURE_ARGS。可以使用=符号指定可选参数。此参数仅附加到--with-entry配置选项。例如

OPTIONS_DEFINE=	OPT1 OPT2
OPT1_CONFIGURE_WITH=	test1
OPT2_CONFIGURE_WITH=	test2=exhaustive

等效于

OPTIONS_DEFINE=	OPT1 OPT2

.include <bsd.port.options.mk>

.if ${PORT_OPTIONS:MOPT1}
CONFIGURE_ARGS+=	--with-test1
.else
CONFIGURE_ARGS+=	--without-test1
.endif

.if ${PORT_OPTIONS:MOPT2}
CONFIGURE_ARGS+=	--with-test2=exhaustive
.else
CONFIGURE_ARGS+=	--without-test2
.endif
5.14.3.3.3. OPT_CONFIGURE_ONOPT_CONFIGURE_OFF

当选择选项OPT时,如果已定义,则OPT_CONFIGURE_ON的值将附加到CONFIGURE_ARGSOPT_CONFIGURE_OFF的工作方式相同,但当选择OPT时。例如

OPTIONS_DEFINE=	OPT1
OPT1_CONFIGURE_ON=	--add-test
OPT1_CONFIGURE_OFF=	--no-test

等效于

OPTIONS_DEFINE=	OPT1

.include <bsd.port.options.mk>

.if ${PORT_OPTIONS:MOPT1}
CONFIGURE_ARGS+=	--add-test
.else
CONFIGURE_ARGS+=	--no-test
.endif

大多数情况下,OPT_CONFIGURE_ENABLEOPT_CONFIGURE_WITH 中的辅助函数提供了更短且更全面的功能。

5.14.3.4. CMAKE_ARGS 辅助函数

5.14.3.4.1. OPT_CMAKE_ONOPT_CMAKE_OFF

当选择选项OPT时,如果已定义,则OPT_CMAKE_ON的值将附加到CMAKE_ARGSOPT_CMAKE_OFF的工作方式相同,但当选择OPT时。例如

OPTIONS_DEFINE=	OPT1
OPT1_CMAKE_ON=	-DTEST:BOOL=true -DDEBUG:BOOL=true
OPT1_CMAKE_OFF=	-DOPTIMIZE:BOOL=true

等效于

OPTIONS_DEFINE=	OPT1

.include <bsd.port.options.mk>

.if ${PORT_OPTIONS:MOPT1}
CMAKE_ARGS+=	-DTEST:BOOL=true -DDEBUG:BOOL=true
.else
CMAKE_ARGS+=	-DOPTIMIZE:BOOL=true
.endif

当值为布尔值时,请参阅 OPT_CMAKE_BOOLOPT_CMAKE_BOOL_OFF 以获取更短的辅助函数。

5.14.3.4.2. OPT_CMAKE_BOOLOPT_CMAKE_BOOL_OFF

当选择选项OPT时,对于OPT_CMAKE_BOOL中的每个entry-D_entry_:BOOL=true将附加到CMAKE_ARGS。当选择选项OPT时,-D_entry_:BOOL=false将附加到CONFIGURE_ARGSOPT_CMAKE_BOOL_OFF则相反,当选择选项时,-D_entry_:BOOL=false附加到CMAKE_ARGS,当选择选项时,-D_entry_:BOOL=true附加到CMAKE_ARGS。例如

OPTIONS_DEFINE=	OPT1
OPT1_CMAKE_BOOL=	TEST DEBUG
OPT1_CMAKE_BOOL_OFF=	OPTIMIZE

等效于

OPTIONS_DEFINE=	OPT1

.include <bsd.port.options.mk>

.if ${PORT_OPTIONS:MOPT1}
CMAKE_ARGS+=	-DTEST:BOOL=true -DDEBUG:BOOL=true \
		-DOPTIMIZE:BOOL=false
.else
CMAKE_ARGS+=	-DTEST:BOOL=false -DDEBUG:BOOL=false \
		-DOPTIMIZE:BOOL=true
.endif

5.14.3.5. MESON_ARGS 辅助函数

5.14.3.5.1. OPT_MESON_ONOPT_MESON_OFF

当选择选项OPT时,如果已定义,则OPT_MESON_ON的值将附加到MESON_ARGSOPT_MESON_OFF的工作方式相同,但当选择OPT时。例如

OPTIONS_DEFINE=	OPT1
OPT1_MESON_ON=	-Dopt=1
OPT1_MESON_OFF=	-Dopt=2

等效于

OPTIONS_DEFINE=	OPT1

.include <bsd.port.options.mk>

.if ${PORT_OPTIONS:MOPT1}
MESON_ARGS+=	-Dopt=1
.else
MESON_ARGS+=	-Dopt=2
.endif
5.14.3.5.2. OPT_MESON_TRUEOPT_MESON_FALSE

当选择选项OPT时,对于OPT_MESON_TRUE中的每个entry-D_entry_=true将附加到MESON_ARGS。当选择选项OPT时,-D_entry_=false将附加到MESON_ARGSOPT_MESON_FALSE则相反,当选择选项时,-D_entry_=false附加到MESON_ARGS,当选择选项时,-D_entry_=true附加到MESON_ARGS。例如

OPTIONS_DEFINE=	OPT1
OPT1_MESON_TRUE=	test debug
OPT1_MESON_FALSE=	optimize

等效于

OPTIONS_DEFINE=	OPT1

.include <bsd.port.options.mk>

.if ${PORT_OPTIONS:MOPT1}
MESON_ARGS+=	-Dtest=true -Ddebug=true \
		-Doptimize=false
.else
MESON_ARGS+=	-Dtest=false -Ddebug=false \
		-Doptimize=true
.endif
5.14.3.5.3. OPT_MESON_YESOPT_MESON_NO

当选择选项OPT时,对于OPT_MESON_YES中的每个entry-D_entry_=yes将附加到MESON_ARGS。当选择选项OPT时,-D_entry_=no将附加到MESON_ARGSOPT_MESON_NO则相反,当选择选项时,-D_entry_=no附加到MESON_ARGS,当选择选项时,-D_entry_=yes附加到MESON_ARGS。例如

OPTIONS_DEFINE=	OPT1
OPT1_MESON_YES=	test debug
OPT1_MESON_NO=	optimize

等效于

OPTIONS_DEFINE=	OPT1

.include <bsd.port.options.mk>

.if ${PORT_OPTIONS:MOPT1}
MESON_ARGS+=	-Dtest=yes -Ddebug=yes \
		-Doptimize=no
.else
MESON_ARGS+=	-Dtest=no -Ddebug=no \
		-Doptimize=yes
.endif
5.14.3.5.4. OPT_MESON_ENABLEDOPT_MESON_DISABLED

当选择选项OPT时,对于OPT_MESON_ENABLED中的每个entry-D_entry_=enabled将附加到MESON_ARGS。当选择选项OPT时,-D_entry_=disabled将附加到MESON_ARGSOPT_MESON_DISABLED则相反,当选择选项时,-D_entry_=disabled附加到MESON_ARGS,当选择选项时,-D_entry_=enabled附加到MESON_ARGS。例如

OPTIONS_DEFINE=	OPT1
OPT1_MESON_ENABLED=	test
OPT1_MESON_DISABLED=	debug

等效于

OPTIONS_DEFINE=	OPT1

.include <bsd.port.options.mk>

.if ${PORT_OPTIONS:MOPT1}
MESON_ARGS+=	-Dtest=enabled -Ddebug=disabled
.else
MESON_ARGS+=	-Dtest=disabled -Ddebug=enabled
.endif

5.14.3.6. OPT_QMAKE_ONOPT_QMAKE_OFF

当选择选项OPT时,如果已定义,则OPT_QMAKE_ON的值将附加到QMAKE_ARGSOPT_QMAKE_OFF的工作方式相同,但当选择OPT时。例如

OPTIONS_DEFINE=	OPT1
OPT1_QMAKE_ON=	-DTEST:BOOL=true
OPT1_QMAKE_OFF=	-DPRODUCTION:BOOL=true

等效于

OPTIONS_DEFINE=	OPT1

.include <bsd.port.options.mk>

.if ${PORT_OPTIONS:MOPT1}
QMAKE_ARGS+=	-DTEST:BOOL=true
.else
QMAKE_ARGS+=	-DPRODUCTION:BOOL=true
.endif

5.14.3.7. OPT_IMPLIES

提供了一种在选项之间添加依赖关系的方法。

当选择OPT时,此变量中列出的所有选项也将被选中。使用前面描述的 OPT_CONFIGURE_ENABLE 来说明

OPTIONS_DEFINE=	OPT1 OPT2
OPT1_IMPLIES=	OPT2

OPT1_CONFIGURE_ENABLE=	opt1
OPT2_CONFIGURE_ENABLE=	opt2

等价于

OPTIONS_DEFINE=	OPT1 OPT2

.include <bsd.port.options.mk>

.if ${PORT_OPTIONS:MOPT1}
CONFIGURE_ARGS+=	--enable-opt1
.else
CONFIGURE_ARGS+=	--disable-opt1
.endif

.if ${PORT_OPTIONS:MOPT2} || ${PORT_OPTIONS:MOPT1}
CONFIGURE_ARGS+=	--enable-opt2
.else
CONFIGURE_ARGS+=	--disable-opt2
.endif
示例 44. OPT_IMPLIES 的简单用法

此端口具有一个X11选项和一个GNOME选项,该选项需要选择X11选项才能构建。

OPTIONS_DEFINE=	X11 GNOME
OPTIONS_DEFAULT=	X11

X11_USES=	xorg
X11_USE=	xorg=xi,xextproto
GNOME_USE=	gnome=gtk30
GNOME_IMPLIES=	X11

5.14.3.8. OPT_PREVENTSOPT_PREVENTS_MSG

提供了一种在选项之间添加冲突的方法。

当选择OPT时,OPT_PREVENTS中列出的所有选项都必须取消选中。如果设置了OPT_PREVENTS_MSG并且触发了冲突,则将显示其内容以解释冲突的原因。例如

OPTIONS_DEFINE=	OPT1 OPT2
OPT1_PREVENTS=	OPT2
OPT1_PREVENTS_MSG=	OPT1 and OPT2 enable conflicting options

大致等价于

OPTIONS_DEFINE=	OPT1 OPT2

.include <bsd.port.options.mk>

.if ${PORT_OPTIONS:MOPT2} && ${PORT_OPTIONS:MOPT1}
BROKEN=	Option OPT1 conflicts with OPT2 (select only one)
.endif

唯一的区别是,第一个将在运行make config后写入错误,建议更改选定的选项。

示例 45. OPT_PREVENTS 的简单用法

此端口具有X509SCTP选项。这两个选项都添加了补丁,但补丁相互冲突,因此不能同时选择它们。

OPTIONS_DEFINE=	X509 SCTP

SCTP_PATCHFILES=	${PORTNAME}-6.8p1-sctp-2573.patch.gz:-p1
SCTP_CONFIGURE_WITH=	sctp

X509_PATCH_SITES=	http://www.roumenpetrov.info/openssh/x509/:x509
X509_PATCHFILES=	${PORTNAME}-7.0p1+x509-8.5.diff.gz:-p1:x509
X509_PREVENTS=		SCTP
X509_PREVENTS_MSG=	X509 and SCTP patches conflict

5.14.3.9. OPT_VARSOPT_VARS_OFF

提供了一种设置和追加变量的通用方法。

在使用OPT_VARSOPT_VARS_OFF之前,请查看 通用变量替换 中是否已经有更具体的辅助函数可用。

当选择选项OPTOPT_VARS已定义时,将从OPT_VARS评估key=valuekey+=value对。=导致KEY的现有值被覆盖,+=追加到值。OPT_VARS_OFF的工作方式相同,但当选择OPT时。

OPTIONS_DEFINE=	OPT1 OPT2 OPT3
OPT1_VARS=	also_build+=bin1
OPT2_VARS=	also_build+=bin2
OPT3_VARS=	bin3_build=yes
OPT3_VARS_OFF=	bin3_build=no

MAKE_ARGS=	ALSO_BUILD="${ALSO_BUILD}" BIN3_BUILD="${BIN3_BUILD}"

等效于

OPTIONS_DEFINE=	OPT1 OPT2

MAKE_ARGS=	ALSO_BUILD="${ALSO_BUILD}" BIN3_BUILD="${BIN3_BUILD}"

.include <bsd.port.options.mk>

.if ${PORT_OPTIONS:MOPT1}
ALSO_BUILD+=	bin1
.endif

.if ${PORT_OPTIONS:MOPT2}
ALSO_BUILD+=	bin2
.endif

.if ${PORT_OPTIONS:MOPT2}
BIN3_BUILD=	yes
.else
BIN3_BUILD=	no
.endif

包含空格的值必须用引号括起来

OPT_VARS=	foo="bar baz"

这是由于 make(1) 变量扩展处理空格的方式。当扩展OPT_VARS= foo=bar baz时,变量最终包含两个字符串,foo=barbaz。但是提交者可能希望只有一个字符串,foo=bar baz。引用该值可以防止空格用作分隔符。

此外,不要var=符号后和值之前添加额外的空格,它也将被分成两个字符串。这将不起作用

OPT_VARS=	foo=	bar

5.14.3.10. 依赖项,OPT_DEPTYPEOPT_DEPTYPE_OFF

对于以下任何依赖项类型

  • PKG_DEPENDS

  • EXTRACT_DEPENDS

  • PATCH_DEPENDS

  • FETCH_DEPENDS

  • BUILD_DEPENDS

  • LIB_DEPENDS

  • RUN_DEPENDS

当选择选项OPT时,如果已定义,则OPT_DEPTYPE的值将附加到DEPTYPEOPT_DEPTYPE_OFF的工作方式相同,但当选择OPT时。例如

OPTIONS_DEFINE=	OPT1
OPT1_LIB_DEPENDS=	liba.so:devel/a
OPT1_LIB_DEPENDS_OFF=	libb.so:devel/b

等效于

OPTIONS_DEFINE=	OPT1

.include <bsd.port.options.mk>

.if ${PORT_OPTIONS:MOPT1}
LIB_DEPENDS+=	liba.so:devel/a
.else
LIB_DEPENDS+=	libb.so:devel/b
.endif

5.14.3.11. 通用变量替换,OPT_VARIABLEOPT_VARIABLE_OFF

对于以下任何变量

  • ALL_TARGET

  • BINARY_ALIAS

  • BROKEN

  • CATEGORIES

  • CFLAGS

  • CONFIGURE_ENV

  • CONFLICTS

  • CONFLICTS_BUILD

  • CONFLICTS_INSTALL

  • CPPFLAGS

  • CXXFLAGS

  • DESKTOP_ENTRIES

  • DISTFILES

  • EXTRACT_ONLY

  • EXTRA_PATCHES

  • GH_ACCOUNT

  • GH_PROJECT

  • GH_SUBDIR

  • GH_TAGNAME

  • GH_TUPLE

  • GL_ACCOUNT

  • GL_COMMIT

  • GL_PROJECT

  • GL_SITE

  • GL_SUBDIR

  • GL_TUPLE

  • IGNORE

  • INFO

  • INSTALL_TARGET

  • LDFLAGS

  • LIBS

  • MAKE_ARGS

  • MAKE_ENV

  • MASTER_SITES

  • PATCHFILES

  • PATCH_SITES

  • PLIST_DIRS

  • PLIST_FILES

  • PLIST_SUB

  • PORTDOCS

  • PORTEXAMPLES

  • SUB_FILES

  • SUB_LIST

  • TEST_TARGET

  • USES

当选择选项OPT时,如果已定义,则OPT_ABOVEVARIABLE的值将附加到ABOVEVARIABLEOPT_ABOVEVARIABLE_OFF的工作方式相同,但当选择OPT时。例如

OPTIONS_DEFINE=	OPT1
OPT1_USES=	gmake
OPT1_CFLAGS_OFF=	-DTEST

等效于

OPTIONS_DEFINE=	OPT1

.include <bsd.port.options.mk>

.if ${PORT_OPTIONS:MOPT1}
USES+=		gmake
.else
CFLAGS+=	-DTEST
.endif

此列表中不包含某些变量,特别是PKGNAMEPREFIXPKGNAMESUFFIX。这是故意的。当端口选项集更改时,端口不得更改其名称。

其中一些变量,至少ALL_TARGETDISTFILESINSTALL_TARGET,在处理选项之后设置其默认值。

Makefile中使用以下行

ALL_TARGET=	all

DOCS_ALL_TARGET=	doc

如果启用了DOCS选项,则ALL_TARGET的最终值为all doc;如果禁用了该选项,则其值为all

Makefile中仅使用选项辅助函数行

DOCS_ALL_TARGET=	doc

如果启用了DOCS选项,则ALL_TARGET的最终值为doc;如果禁用了该选项,则其值为all

5.14.3.12. 附加构建目标,target-OPT-ontarget-OPT-off

这些Makefile目标可以接受可选的额外构建目标

  • pre-fetch

  • do-fetch

  • post-fetch

  • pre-extract

  • do-extract

  • post-extract

  • pre-patch

  • do-patch

  • post-patch

  • pre-configure

  • do-configure

  • post-configure

  • pre-build

  • do-build

  • post-build

  • pre-install

  • do-install

  • post-install

  • post-stage

  • pre-package

  • do-package

  • post-package

当选择选项OPT时,如果已定义,则在TARGET之后执行目标TARGET-OPT-onTARGET-OPT-off的工作方式相同,但当选择OPT时。例如

OPTIONS_DEFINE=	OPT1

post-patch-OPT1-on:
	@${REINPLACE_CMD} -e '/opt1/s|/usr/bin/|${EXAMPLESDIR}/|' ${WRKSRC}/Makefile

post-patch-OPT1-off:
	@${REINPLACE_CMD} -e '/opt1/s|/usr/bin/|${PREFIX}/bin/|' ${WRKSRC}/Makefile

等效于

OPTIONS_DEFINE=	OPT1

.include <bsd.port.options.mk>

post-patch:
.if ${PORT_OPTIONS:MOPT1}
	@${REINPLACE_CMD} -e '/opt1/s|/usr/bin/|${EXAMPLESDIR}/|' ${WRKSRC}/Makefile
.else
	@${REINPLACE_CMD} -e '/opt1/s|/usr/bin/|${PREFIX}/bin/|' ${WRKSRC}/Makefile
.endif

5.15. 指定工作目录

每个端口都提取到一个必须可写的目录中。端口系统默认为将DISTFILES解压到名为${DISTNAME}的目录中。换句话说,如果Makefile具有

PORTNAME=	foo
DISTVERSION=	1.0

则端口的发行版文件包含一个顶级目录foo-1.0,其余文件位于该目录下。

如果情况并非如此,则可以覆盖许多变量。

5.15.1. WRKSRC

此变量列出了提取应用程序的 distfiles 时创建的目录的名称。如果我们之前的示例提取到名为 foo(而不是 foo-1.0)的目录中,则编写

WRKSRC=	${WRKDIR}/foo

或者可能

WRKSRC=	${WRKDIR}/${PORTNAME}

5.15.2. WRKSRC_SUBDIR

如果端口所需的源文件位于提取的分布文件子目录中,请将 WRKSRC_SUBDIR 设置为该目录。

WRKSRC_SUBDIR=	src

5.15.3. NO_WRKSUBDIR

如果端口根本不提取到子目录中,则设置 NO_WRKSUBDIR 以指示这一点。

NO_WRKSUBDIR=	yes

因为 WRKDIR 是构建期间唯一应该可写的目录,并且用于存储记录构建状态的许多文件,所以端口的提取将被强制到子目录中。

5.16. 冲突处理

有三个不同的变量用于注册包和端口之间的冲突:CONFLICTSCONFLICTS_INSTALLCONFLICTS_BUILD

冲突变量会自动设置变量 IGNORE,该变量在 使用 BROKEN 标记端口不可安装 中有更详细的说明。

在删除多个冲突端口中的一个时,建议在其他端口中保留 CONFLICTS 几个月,以满足那些偶尔更新的用户。

CONFLICTS_INSTALL

如果软件包无法与其他软件包共存(由于文件冲突、运行时不兼容等)。CONFLICTS_INSTALL 检查在构建阶段之后和安装阶段之前进行。

CONFLICTS_BUILD

如果在已安装其他特定端口时无法构建端口。构建冲突不会记录在生成的软件包中。

CONFLICTS

如果某个端口已安装,则无法构建端口,并且生成的软件包无法与其他软件包共存。CONFLICTS 检查在构建阶段之前和安装阶段之前进行。

CONFLICTS* 变量值的每个空格分隔项都与除正在构建的软件包之外的软件包匹配,使用 shell 通配符规则。这允许在冲突列表中列出端口的所有变体,而不必费力地从该列表中排除正在构建的变体。例如,如果安装了 git-lite,CONFLICTS_INSTALL=git git-lite 将允许执行

% make -C devel/git FLAVOR=lite all deinstall install

但是以下命令将报告冲突,因为安装的软件包基本名称为 git-lite,而 git 将被构建,但不能与 git-lite 一起安装。

% make -C devel/git FLAVOR=default all deinstall install

如果没有此功能,Makefile 将需要每个变体一个 _flavor__CONFLICTS_INSTALL,列出所有其他变体。

这些变量中最常见的内容是另一个端口的软件包基本名称。软件包基本名称是不带附加版本的软件包名称,可以通过运行 make -V PKGBASE 获得。

示例 46. CONFLICTS* 的基本用法

dns/bind99 如果存在 dns/bind910 则无法安装,因为它们安装了相同的文件。首先收集要使用的软件包基本名称

% make -C dns/bind99 -V PKGBASE
bind99
% make -C dns/bind910 -V PKGBASE
bind910

然后添加到 dns/bind99Makefile

CONFLICTS_INSTALL=	bind910

并添加到 dns/bind910Makefile

CONFLICTS_INSTALL=	bind99

有时,只有另一个端口的某些版本不兼容。在这种情况下,使用包含版本的完整软件包名称。如有必要,使用 shell 通配符(如 *?),以便匹配所有必要的版本。

示例 47. 使用带有通配符的 CONFLICTS*

从 2.0 版到 2.4.1_2 版,deskutils/gnotime 用于安装 databases/qof 的捆绑版本。

为了反映过去,databases/qofMakefile 包含

CONFLICTS_INSTALL=	gnotime-2.[0-3]* \
			gnotime-2.4.0* gnotime-2.4.1 \
			gnotime-2.4.1_[12]

第一个条目匹配版本 2.02.3,第二个匹配 2.4.0 的所有修订版,第三个匹配确切的 2.4.1 版本,最后一个匹配 2.4.1 版本的第一和第二个修订版。

deskutils/gnotime 没有任何冲突行,因为其当前版本与任何其他内容都不冲突。

在创建不受冲突影响的目标时,可以临时设置变量 DISABLE_CONFLICTS。此变量不应在端口 Makefile 中设置。

% make -DDISABLE_CONFLICTS patch

5.17. 安装文件

install 阶段对最终用户非常重要,因为它将文件添加到他们的系统中。端口 Makefile*-install 目标中运行的所有附加命令都应回显到屏幕上。不要使用 @.SILENT 使这些命令静默。

5.17.1. INSTALL_*

使用 bsd.port.mk 中提供的宏来确保端口的 *-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 目标中完成。例如

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) 报告为 strippednot stripped。此外,strip(1) 将检测已剥离的程序并干净地退出。

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

框架提供的变量(STRIP_CMDINSTALL_PROGRAMINSTALL_LIB 等)和 USES 会自动处理此问题。

某些软件会将其 LDFLAGS 添加 -s,在这种情况下,如果设置了 WITH_DEBUG,则删除 -s,或者无条件删除它并在 post-install 中使用 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})

此示例将 vendor distfile 中 examples 目录的内容安装到端口的正确示例位置。

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

此示例将夏季月份的数据安装到 DATADIRsummer 子目录中。

可以通过 COPYTREE_* 宏的第三个参数传递其他 find 参数。例如,要安装第一个示例中的所有文件(除了 Makefile),可以使用以下命令。

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. 安装其他文档

如果软件有一些除了标准手册页和 info 页之外对用户有用的文档,请将其安装在 DOCSDIR 下。这可以通过与上一项相同的方式在 post-install 目标中完成。

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

由于只有 pkg-plist 中列出的文件被安装,因此始终安全地将文档安装到 STAGEDIR(请参阅 暂存)。因此,仅当已安装的文件足够大以导致明显的 I/O 负载时,才需要 .if 块。

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

另一方面,如果端口中存在 DOCS 选项,请在 post-install-DOCS-on 目标中安装文档。这些目标在 其他构建目标 中进行了描述。

以下是某些方便的变量,以及它们在 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 中的额外文档。它不适用于标准的手册页和信息页。安装在 EXAMPLESDIR 中的内容由 EXAMPLES 选项控制。

这些变量被导出到 PLIST_SUB。如果可能,它们的值将作为相对于 PREFIX 的路径名出现在那里。也就是说,share/doc/PORTNAME 将在打包列表中默认为 %%DOCSDIR%% 进行替换,依此类推。(有关 pkg-plist 替换的更多信息,请参见 此处。)

所有条件安装的文档文件和目录都包含在 pkg-plist 中,并带有 %%PORTDOCS%% 前缀,例如

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

作为在 pkg-plist 中枚举文档文件的替代方案,端口可以将变量 PORTDOCS 设置为要添加到最终打包列表的文件名和 shell 通配符模式列表。这些名称将相对于 DOCSDIR。因此,使用 PORTDOCS 并为其文档使用非默认位置的端口必须相应地设置 DOCSDIR。如果 PORTDOCS 中列出了目录或与来自此变量的通配符模式匹配,则包含的文件和目录的整个子树将在最终打包列表中注册。如果 DOCS 选项已被取消设置,则 PORTDOCS 中列出的文件和目录将不会被安装或添加到端口打包列表中。如上所示,在 PORTDOCS 中安装文档仍然由端口本身决定。使用 PORTDOCS 的典型示例

PORTDOCS=	README.* ChangeLog docs/*

分别安装在 DATADIREXAMPLESDIR 下的文件的 PORTDOCS 等价物为 PORTDATAPORTEXAMPLES

pkg-message 的内容在安装时显示。有关详细信息,请参见 使用 pkg-message 的部分pkg-message 不需要添加到 pkg-plist 中。

5.17.5. PREFIX 下的子目录

尝试让端口将内容放在 PREFIX 的正确子目录中。某些端口将所有内容都放在端口名称的子目录中,这是不正确的。此外,许多端口将除二进制文件、头文件和手册页之外的所有内容都放在 lib 的子目录中,这与 BSD 范例不兼容。许多文件必须移动到以下目录之一:etc(设置/配置文件)、libexec(内部启动的可执行文件)、sbin(超级用户/管理员的可执行文件)、info(信息浏览器的文档)或 share(与架构无关的文件)。有关详细信息,请参见 hier(7);管理 /usr 的规则也几乎适用于 /usr/local。例外情况是处理 USENET “新闻” 的端口。它们可以使用 PREFIX/news 作为其文件的目标位置。

5.18. 使用 BINARY_ALIAS 重命名命令而不是修补构建

定义 BINARY_ALIAS 时,它将在一个目录中创建给定命令的符号链接,该目录将被添加到 PATH 的开头。

使用它来替换构建阶段依赖的硬编码命令,而无需修补任何构建文件。

示例 48. 使用 BINARY_ALIAS 使 gsed 可用作 sed

某些端口期望 sed 的行为类似于 GNU sed,并使用 sed(1) 未提供的功能。GNU sed 可从 FreeBSD 上的 textproc/gsed 获取。

使用 BINARY_ALIAS 在构建期间用 gsed 替换 sed

BUILD_DEPENDS=	gsed:textproc/gsed
...
BINARY_ALIAS=	sed=gsed
示例 49. 使用 BINARY_ALIAS 为硬编码的 python3 命令提供别名

在构建脚本中对 python3 进行硬编码引用的端口需要在构建时将其提供给 PATH。使用 BINARY_ALIAS 创建一个指向正确的 Python 3 二进制文件的别名

USES=	python:3.4+,build
...
BINARY_ALIAS=	python3=${PYTHON_CMD}

有关 USES=python 的更多信息,请参见 使用 Python

二进制别名在通过 BUILD_DEPENDSLIB_DEPENDS 提供的依赖项处理完毕且在 configure 目标之前创建。这会导致各种限制。例如,通过 TEST_DEPENDS 安装的程序不能用于创建二进制别名,因为以这种方式指定的测试依赖项在创建二进制别名之后进行处理。


上次修改时间:2024 年 9 月 23 日,作者 Fernando Apesteguía