#include <sys/param.h>
第 13 章. 注意事项
目录
13.2. WRKDIR
不要向 WRKDIR
外部的文件写入任何内容。WRKDIR
是唯一一个保证在端口构建期间可写的位置(请参阅 从 CDROM 安装端口 以了解从只读树构建端口的示例)。pkg-* 文件可以通过 重新定义变量 来修改,而不是覆盖文件。
13.3. WRKDIRPREFIX
确保端口遵守 WRKDIRPREFIX
。大多数端口不需要担心这个问题。特别是,当引用另一个端口的 WRKDIR
时,请注意正确的位置是 ${WRKDIRPREFIX}${PORTSDIR}/subdir/name/work,而不是 ${PORTSDIR}/subdir/name/work 或 ${.CURDIR}/../../subdir/name/work 或类似的位置。
13.4. 区分操作系统和操作系统版本
某些代码需要根据其运行的 FreeBSD Unix 版本进行修改或条件编译。区分 FreeBSD 版本的首选方法是 sys/param.h 中定义的 __FreeBSD_version
和 __FreeBSD__
宏。如果未包含此文件,请在 .c 文件的适当位置添加以下代码:
。
__FreeBSD__
在所有版本的 FreeBSD 中都定义为其主版本号。例如,在 FreeBSD 9.x 中,__FreeBSD__
定义为 9
。
#if __FreeBSD__ >= 9 # if __FreeBSD_version >= 901000 /* 9.1+ release specific code here */ # endif #endif
__FreeBSD_version
值的完整列表可在 __FreeBSD_version 值 中找到。
13.5. 在 bsd.port.mk 之后编写内容
不要在.include <bsd.port.mk>
行之后编写任何内容。通常可以通过在Makefile的中间某个位置包含bsd.port.pre.mk并在末尾包含bsd.port.post.mk来避免这种情况。
仅包含bsd.port.pre.mk/bsd.port.post.mk对或bsd.port.mk;不要混合这两种用法。 |
bsd.port.pre.mk仅定义了一些变量,这些变量可以在Makefile中的测试中使用,bsd.port.post.mk定义了其余部分。
以下是bsd.port.pre.mk中定义的一些重要变量(这不是完整列表,请阅读bsd.port.mk以获取完整列表)。
变量 | 描述 |
---|---|
| 由 |
| 由 |
| 操作系统的发行版本(例如, |
| 操作系统的数字版本;与 |
| "本地"树的基目录(例如, |
| 端口安装自身的位置(请参阅有关 |
当需要 |
以下是一些可以在bsd.port.pre.mk之后添加的内容示例
# no need to compile lang/perl5 if perl5 is already in system .if ${OSVERSION} > 300003 BROKEN= perl is in system .endif
在BROKEN=
之后始终使用制表符而不是空格。
13.6. 在包装脚本中使用exec
语句
如果端口安装了一个其目的是启动另一个程序的shell脚本,并且如果启动该程序是脚本执行的最后一个操作,请确保使用exec
语句启动该程序,例如
#!/bin/sh exec %%LOCALBASE%%/bin/java -jar %%DATADIR%%/foo.jar "$@"
exec
语句用指定的程序替换shell进程。如果省略exec
,则shell进程会在程序执行期间保留在内存中,并无谓地消耗系统资源。
13.7. 合理地做事
Makefile应该以简单合理的方式执行操作。使其缩短几行或更具可读性总是更好。例如,使用make的.if
结构而不是shell的if
结构,如果重新定义EXTRACT*
足够,则不要重新定义do-extract
,以及使用GNU_CONFIGURE
而不是CONFIGURE_ARGS += --prefix=${PREFIX}
。
如果需要大量新代码来执行某些操作,则可能已经在bsd.port.mk中实现了它。虽然难以阅读,但对于许多看似困难的问题,bsd.port.mk已经提供了简写解决方案。
13.8. 尊重CC
和CXX
端口必须同时尊重CC
和CXX
。我们的意思是,端口不得绝对设置这些变量的值,覆盖现有值;相反,它可以将它需要的任何值附加到现有值。这样,影响所有端口的构建选项可以在全局范围内设置。
如果端口不尊重这些变量,请将NO_PACKAGE=ignores either cc or cxx
添加到Makefile中。
这是一个尊重CC
和CXX
的Makefile示例。请注意?=
CC?= gcc
CXX?= g++
这是一个既不尊重CC
也不尊重CXX
的示例
CC= gcc
CXX= g++
CC
和CXX
都可以在FreeBSD系统中的/etc/make.conf中定义。第一个示例在之前未在/etc/make.conf中设置值的情况下定义一个值,保留任何系统范围的定义。第二个示例覆盖之前定义的任何内容。
13.9. 尊重CFLAGS
端口必须尊重CFLAGS
。我们的意思是,端口不得绝对设置此变量的值,覆盖现有值。相反,它可以将它需要的任何值附加到现有值。这样,影响所有端口的构建选项可以在全局范围内设置。
如果它没有这样做,请将NO_PACKAGE=ignores cflags
添加到Makefile中。
这是一个尊重CFLAGS
的Makefile示例。请注意+=
CFLAGS+= -Wall -Werror
这是一个不尊重CFLAGS
的示例
CFLAGS= -Wall -Werror
CFLAGS
在FreeBSD系统中的/etc/make.conf中定义。第一个示例将其他标志附加到CFLAGS
,保留任何系统范围的定义。第二个示例覆盖之前定义的任何内容。
从第三方Makefile中删除优化标志。系统CFLAGS
包含系统范围的优化标志。来自未修改Makefile的示例
CFLAGS= -O3 -funroll-loops -DHAVE_SOUND
使用系统优化标志,Makefile看起来类似于此示例
CFLAGS+= -DHAVE_SOUND
13.10. 详细的构建日志
使端口构建系统显示在构建阶段执行的所有命令。完整的构建日志对于调试端口问题至关重要。
非信息性构建日志示例(错误)
CC source1.o CC source2.o CCLD someprogram
详细构建日志示例(正确)
cc -O2 -pipe -I/usr/local/include -c -o source1.o source1.c cc -O2 -pipe -I/usr/local/include -c -o source2.o source2.c cc -o someprogram source1.o source2.o -L/usr/local/lib -lsomelib
某些构建系统(例如CMake、ninja和GNU configure)由端口框架设置为详细记录。在其他情况下,端口可能需要单独的调整。
13.12. README.html
README.html不是端口的一部分,而是由make readme
生成的。不要在补丁或提交中包含此文件。
如果 |
13.13. 使用BROKEN
、FORBIDDEN
或IGNORE
标记端口不可安装
在某些情况下,必须阻止用户安装端口。端口的Makefile中可以使用多个变量来告诉用户该端口无法安装。这些make变量的值将是向用户显示的端口拒绝安装自身的原因。请使用正确的make变量。每个变量都向用户和依赖于Makefile的自动化系统(例如端口构建集群和FreshPorts)传达截然不同的含义。
13.13.1. 变量
BROKEN
保留用于当前无法正确编译、安装、卸载或运行的端口。将其用于认为问题是暂时的端口。如果得到指示,构建集群仍将尝试构建它们以查看底层问题是否已解决。(但是,通常情况下,集群在没有此功能的情况下运行。)
例如,当端口
无法编译
其配置或安装过程失败
在${PREFIX}之外安装文件
在卸载时无法干净地删除所有文件(但是,端口保留用户修改的文件可能是可以接受的,也是理想的)
在应该正常运行的系统上存在运行时问题。
FORBIDDEN
用于包含安全漏洞或引发对安装了给定端口的FreeBSD系统安全性的严重担忧的端口(例如,声誉不佳的不安全程序或提供易于利用的服务的程序)。一旦某个软件存在漏洞并且没有发布升级,就将端口标记为FORBIDDEN
。理想情况下,在发现安全漏洞后尽快升级端口,以减少易受攻击的FreeBSD主机数量(我们希望以安全著称),但是有时在公开漏洞和发布易受攻击软件的更新版本之间存在明显的时差。不要出于任何其他安全原因以外的任何原因将端口标记为FORBIDDEN
。IGNORE
保留用于必须出于其他原因而未构建的端口。将其用于认为问题是结构性的端口。构建集群在任何情况下都不会构建标记为IGNORE
的端口。例如,当端口在已安装的FreeBSD版本上不起作用
具有可能由于许可限制而无法自动获取的distfile
与其他一些已安装的端口不兼容(例如,端口依赖于www/drupal7,但安装了www/drupal8)
如果端口与当前已安装的端口发生冲突(例如,如果它们在执行不同功能的同一位置安装文件),请改用
CONFLICTS
。CONFLICTS
将自行设置IGNORE
。
13.14. 体系结构注意事项
13.14.1. 体系结构的一般说明
FreeBSD 在比众所周知的基于 x86 的架构更多的处理器架构上运行。某些端口具有特定于这些体系结构之一或更多体系结构的约束。
要查看支持的体系结构列表,请运行
cd ${SRCDIR}; make targets
这些值以TARGET
/TARGET_ARCH
的形式显示。端口只读makevar ARCH
根据TARGET_ARCH
的值设置。端口Makefile应该测试此Makevar的值。
13.14.2. 将端口标记为体系结构中立
通过设置NO_ARCH=yes
来识别没有任何体系结构相关文件或要求的端口。
从这些端口构建的软件包的体系结构字符串以:*
(通配符体系结构)结尾,而不是例如freebsd:13:x86:64
(amd64体系结构)。
|
13.14.3. 将端口标记为仅在某些体系结构上被忽略
要将端口标记为仅在某些体系结构上被
IGNORE
,还有两个其他便捷变量会自动设置IGNORE
:ONLY_FOR_ARCHS
和NOT_FOR_ARCHS
。示例ONLY_FOR_ARCHS= i386 amd64
NOT_FOR_ARCHS= ia64 sparc64
可以使用
ONLY_FOR_ARCHS_REASON
和NOT_FOR_ARCHS_REASON
设置自定义IGNORE
消息。可以使用ONLY_FOR_ARCHS_REASON_ARCH
和NOT_FOR_ARCHS_REASON_ARCH
进行每个体系结构条目。
如果端口获取 i386 二进制文件并安装它们,则设置
IA32_BINARY_PORT
。如果设置了此变量,则必须存在/usr/lib32以用于 IA32 版本的库,并且内核必须支持 IA32 兼容性。如果这两个依赖项之一未满足,则IGNORE
将自动设置。
13.15. 使用DEPRECATED
或EXPIRATION_DATE
标记要删除的端口
请记住,如果端口无法工作,BROKEN
和FORBIDDEN
仅应作为临时解决方案使用。永久损坏的端口将完全从树中删除。
在有意义的情况下,可以使用DEPRECATED
和EXPIRATION_DATE
警告用户即将删除端口。前者是一个字符串,说明为什么计划删除该端口;后者是 ISO 8601 格式(YYYY-MM-DD)的字符串。两者都将显示给用户。
可以设置DEPRECATED
而没有EXPIRATION_DATE
(例如,推荐端口的更新版本),但反过来没有任何意义。
在将端口标记为 |
关于需要给出多少通知没有既定的策略。目前的做法似乎是针对安全相关问题一个月,针对构建问题两个月。这也给了任何感兴趣的提交者一些时间来解决问题。
13.16. 避免使用.error
构造
Makefile指示由于某些外部因素(例如,用户指定了构建选项的非法组合)而无法安装端口的正确方法是将非空白值设置为IGNORE
。make install
将格式化此值并显示给用户。
为此目的使用.error
是一个常见的错误。这样做的问题在于,许多与端口树一起工作的自动化工具在这种情况下都会失败。最常见的发生情况是在尝试构建/usr/ports/INDEX时(请参阅运行make describe
)。但是,即使是更简单的命令,如make maintainer
,在这种情况下也会失败。这是不可接受的。
.error
接下来的两个Makefile代码段中的第一个将导致make index
失败,而第二个则不会。
.error "option is not supported"
IGNORE=option is not supported
13.17. sysctl 的用法
不鼓励使用sysctl,除非在目标中。这是因为任何makevar
的评估(例如,在make index
期间使用)必须运行该命令,从而进一步减慢该过程。
仅通过SYSCTL
使用sysctl(8),因为它包含完整限定路径并且可以被覆盖,如果有人有这样的特殊需求。
13.18. 重新滚动发行版文件
有时软件作者会更改已发布发行版文件的内容,而不更改文件名称。验证更改是否为官方更改,并且是由作者执行的。过去曾发生过发行版文件在下载服务器上被静默更改,目的是造成损害或危害最终用户安全的情况。
将旧的发行版文件放在一边,下载新的文件,解压缩它们并使用diff(1)比较内容。如果没有可疑之处,请更新distinfo。
请务必在 PR 和提交日志中总结差异,以便其他人知道没有任何不良事件发生。 |
联系软件作者并与他们确认更改。
13.19. 使用 POSIX 标准
FreeBSD 端口通常期望符合 POSIX 标准。某些软件和构建系统基于特定操作系统或环境做出假设,这在端口中使用时可能会导致问题。
如果还有其他获取信息的方法,请不要使用/proc。例如,在main()
中使用setprogname(argv[0])
,然后使用getprogname(3)来了解可执行文件名。
不要依赖 POSIX 未记录的行为。
如果应用程序也可以在没有时间戳的情况下工作,请不要在应用程序的关键路径中记录时间戳。获取时间戳可能会很慢,具体取决于操作系统中时间戳的准确性。如果确实需要时间戳,请确定它们需要多精确,并使用一个 API,该 API 文档记录了仅提供所需精度的功能。
一些简单的系统调用(例如gettimeofday(2)、getpid(2))在 Linux® 上比在任何其他操作系统上都快得多,这是由于缓存和 vsyscall 性能优化。不要依赖它们在性能关键型应用程序中很便宜。一般来说,如果可能,请尽量避免使用系统调用。
不要依赖 Linux® 特定的套接字行为。特别是,默认套接字缓冲区大小不同(使用SO_SNDBUF
和SO_RCVBUF
调用setsockopt(2),并且当套接字缓冲区已满时,Linux® 的send(2)会阻塞,而 FreeBSD 的会失败并在 errno 中设置ENOBUFS
。
如果需要依赖非标准行为,请将其正确封装到通用 API 中,在配置阶段检查该行为,如果缺少则停止。
查看手册页以查看所使用的函数是否是 POSIX 接口(在手册页的“标准”部分)。
不要假设/bin/sh是 bash。确保传递给system(3)的命令行可以在符合 POSIX 标准的 shell 中工作。
常见的 bashisms 列表可在此处找到。
检查头文件是否以 POSIX 或手册页推荐的方式包含。例如,经常会忘记sys/types.h,这对 Linux® 来说不是什么大问题,但对 FreeBSD 来说却是一个问题。
最后修改于:2024 年 3 月 9 日,作者:Danilo G. Baio