第 6 章 特殊情况
本节说明了创建 Port 时需要考虑的最常见事项。
6.1. 拆分长文件
有时,Port 的 Makefile 可能会非常长。例如,Rust Port 的 CARGO_CRATES 列表可能很长,或者 Makefile 中可能包含根据架构不同而变化的代码。在这种情况下,将原始的 Makefile 拆分成多个文件可能会很方便。bsd.port.mk 会自动包含一些类型的 Makefile 到主 Port Makefile 中。
框架会自动处理以下文件类型(如果发现它们的话):
Makefile.crates。可以在 audio/ebur128 中找到示例。
Makefile.inc。可以在 net/ntp 中找到示例。
Makefile.${ARCH}-${OPSYS}
Makefile.${OPSYS}。可以在 net/cvsup-static 中找到示例。
Makefile.${ARCH}
Makefile.local
通常的做法是,如果包装列表在不同架构之间变化很大,或者依赖于所选的 flavor,那么将 Port 的包装列表拆分成多个文件。在这种情况下,每个架构的 pkg-plist 文件命名遵循 pkg-plist.${ARCH} 或 pkg-plist.${FLAVOR} 的模式。如果存在多个 pkg-plist 文件,框架不会自动创建包装列表。Port 作者需要选择适当的 pkg-plist 文件并将其分配给 PLIST 变量。关于如何处理这个问题的示例可以在 audio/logitechmediaserver 和 deskutils/libportal 中找到。
6.2. Staging
bsd.port.mk 要求 Port 使用 "阶段目录"。这意味着 Port 必须将文件安装到一个单独的目录,而不是直接安装到常规的目标目录(例如,PREFIX)。然后从这个阶段目录构建包。在许多情况下,这不需要 root 权限,从而使得可以作为非特权用户构建包。通过 staging,Port 被构建并安装到阶段目录 STAGEDIR 中。然后从该目录创建包,并安装到系统中。Automake 工具称这一概念为 DESTDIR,但在 FreeBSD 中,DESTDIR 有不同的含义(见 PREFIX 和 DESTDIR)。
注意
没有任何 Port 真正 需要 root 权限。通过使用
USES=uidfix大多数情况下可以避免。如果 Port 仍然运行像 chown(8)、chgrp(1),或者通过 install(1) 强制设置文件的所有者或组,则应使用USES=fakeroot来伪造这些调用。此时可能需要对 Port 的 Makefiles 进行一些补丁。
元 Port(即不安装文件,而是依赖于其他 Port 的 Port)必须避免不必要地将 mtree(8) 提取到阶段目录。这是包的基本目录布局,这些空目录会被视为孤立的。为了防止 mtree(8) 提取,可以添加这一行:
技巧
元 Port 应该使用
USES=metaport。它为不获取、构建或安装任何东西的 Port 设置默认值。
Staging 通过在 pre-install、do-install 和 post-install 目标中使用 STAGEDIR 前缀来启用(参见本书中的示例)。通常,这包括 PREFIX、ETCDIR、DATADIR、EXAMPLESDIR、DOCSDIR 等。目录应该作为 post-install 目标的一部分创建。尽量避免使用绝对路径。
技巧
安装内核模块的 Port 必须在其目标路径(默认为 /boot/modules)前添加
STAGEDIR。
6.2.1. 处理符号链接
在创建符号链接时,强烈建议使用相对链接。使用 ${RLN} 可以自动创建相对符号链接。它在后台使用 install(1),自动计算要创建的相对链接。
示例 1. 自动创建相对符号链接
${RLN} 使用 install(1) 的相对符号链接功能,使得创建者不必手动计算相对路径。
将生成:
6.3. 捆绑的库
本节解释了为什么捆绑的依赖库被认为是不好的,以及如何处理它们。
6.3.1. 为什么捆绑的库不好
一些软件要求开发者找到第三方库并将所需的依赖添加到 Port 中。其他软件则将所有必需的库打包在分发文件中。第二种方法看起来一开始更容易,但存在一些严重的缺点:
以下列表大致基于 Fedora 和 Gentoo 的维基页面,均由 CC-BY-SA 3.0 许可证授权。
安全性
如果在上游库中发现漏洞并进行修复,可能不会在与 Port 捆绑的库中修复这些漏洞。一个原因可能是作者没有意识到这个问题。这意味着开发者必须修复它们,或升级到一个无漏洞的版本,并向作者提交补丁。这一过程需要时间,导致软件暴露在漏洞风险中的时间比必要的更长。这反过来使得协调修复变得更加困难,且难以避免不必要地泄漏漏洞信息。
错误
这个问题类似于上一段提到的安全问题,但一般不如安全问题严重。
分叉
库被捆绑后,作者更容易对上游库进行分叉。虽然从表面上看,这样做更方便,但这意味着代码与上游分叉,使得解决安全问题或其他问题变得更加困难。原因之一是补丁变得更难以应用。
分叉的另一个问题是,由于代码与上游分叉,bug 需要重复解决,而不是集中在一个地方解决。这违背了开源软件的初衷。
符号冲突
当系统中已安装了某个库时,它可能会与捆绑版本发生冲突。这可能会导致编译或链接时立即出错,也可能导致运行时错误,后者可能更难追踪。后一种问题可能是因为两个库的版本不兼容。
许可问题
当捆绑来自不同来源的项目时,许可问题可能更容易出现,尤其是当许可不兼容时。
资源浪费
捆绑的库在多个层面上浪费资源。特别是当这些库已经存在于系统上时,构建实际应用的时间会变得更长。在运行时,它们可能占用不必要的内存,而系统全局库已经被其他程序加载,而捆绑的库却由另一个程序加载。
努力的浪费
当某个库需要为 FreeBSD 打补丁时,这些补丁必须再次应用到捆绑库中。这浪费了开发者的时间,因为这些补丁可能无法干净地应用。并且很难发现这些补丁其实是必需的。
6.3.2. 如何处理捆绑的库
尽可能使用未捆绑版本的库,通过向 Port 添加 LIB_DEPENDS 来指定依赖。如果这种 Port 还不存在,考虑创建一个新的 Port。
仅在上游有良好的安全记录并且使用未捆绑版本会导致过于复杂的补丁时,才使用捆绑库。
重要
在一些非常特殊的情况下,例如仿真器(如 Wine),Port 必须捆绑库,因为这些库属于不同架构,或者它们已被修改以适应软件的需求。在这种情况下,这些库不应该暴露给其他 Port 进行链接。可以在 Port 的 Makefile 中添加
BUNDLE_LIBS=yes。这将告诉 pkg(8) 不计算提供的库。在将此添加到 Port 之前,请始终向 Ports 管理团队 <portmgr@FreeBSD.org> 询问。
6.4. 共享库
如果 Port 安装一个或多个共享库,定义 USE_LDCONFIG make 变量,指示 bsd.port.mk 在 post-install 目标阶段运行 ${LDCONFIG} -m,该命令将在新库安装的目录(通常是 PREFIX/lib)上运行,以将其注册到共享库缓存中。定义此变量时,它还会在 pkg-plist 中添加适当的 @exec /sbin/ldconfig -m 和 @unexec /sbin/ldconfig -R,以便用户安装软件包后能立即使用共享库,并且卸载时不会让系统仍然认为库存在。
可以通过将 USE_LDCONFIG 设置为共享库安装目录的列表,来覆盖默认目录。例如,如果 Port 将共享库安装到 PREFIX/lib/foo 和 PREFIX/lib/bar,则在 Makefile 中使用以下设置:
请仔细检查,通常这并不总是必要的,或者可以通过 -rpath 或在链接时设置 LD_RUN_PATH 来避免(参见 lang/mosml 示例),或者通过像 www/seamonkey 那样的 shell 脚本包装器,先设置 LD_LIBRARY_PATH 后再调用二进制文件。
在 64 位系统上安装 32 位库时,使用 USE_LDCONFIG32。
如果软件使用 autotools,特别是 libtool,则添加 USES=libtool。
当库的主版本号在新版本 Port 更新时增加时,所有链接到受影响库的其他 Port 必须增加 PORTREVISION,以强制使用新库版本重新编译。
6.5. 有分发限制或法律问题的 Ports
许可证各不相同,其中一些对应用程序如何打包、是否可以盈利性销售等方面有一定限制。
重要
Port 维护者有责任阅读软件的许可条款,并确保 FreeBSD 项目不会因通过 FTP/HTTP 或 CD-ROM 再分发源代码或已编译的二进制文件而违反许可条款并被追究责任。如果有疑问,请联系 FreeBSD ports 邮件列表。
在这种情况下,可以设置下节中说明的变量。
6.5.1. NO_PACKAGE
此变量表示我们不能生成应用程序的二进制包。例如,许可协议可能禁止二进制再分发,或者可能禁止从修补过的源代码创建的包的分发。
然而,Port 的 DISTFILES 可以自由地在 FTP/HTTP 上镜像。它们也可以分发到 CD-ROM(或类似媒体),除非同时设置了 NO_CDROM。
如果二进制包没有普遍的用途,并且必须始终从源代码编译应用程序,请使用 NO_PACKAGE。例如,如果应用程序在编译时硬编码了与站点特定的配置信息,请设置 NO_PACKAGE。
设置 NO_PACKAGE 为说明为什么不能生成包的字符串。
6.5.2. NO_CDROM
仅此变量表示,尽管我们允许生成二进制包,但我们不能将这些包或 Port 的 DISTFILES 放到 CD-ROM(或类似媒体)上进行转售。然而,二进制包和 Port 的 DISTFILES 仍然可以通过 FTP/HTTP 进行分发。
如果同时设置了 NO_PACKAGE 和 NO_CDROM,则只有 Port 的 DISTFILES 可用,并且仅通过 FTP/HTTP 分发。
设置 NO_CDROM 为说明为什么不能在 CD-ROM 上重新分发该 Port 的字符串。例如,如果该 Port 的许可证仅允许“非商业”使用,可以使用此设置。
6.5.3. NOFETCHFILES
在 NOFETCHFILES 中定义的文件不能从任何 MASTER_SITES 获取。例如,当文件由供应商提供在 CD-ROM 上时,就是一个这样的文件。
检查这些文件是否在 MASTER_SITES 上可用的工具需要忽略这些文件,并且不报告它们的可用性。
6.5.4. RESTRICTED
如果应用程序的许可既不允许镜像应用程序的 DISTFILES 也不允许以任何方式分发二进制包,请单独设置此变量。
不要与 RESTRICTED 一起设置 NO_CDROM 或 NO_PACKAGE,因为后者变量已经包含了前者的含义。
将 RESTRICTED 设置为说明为何该 Port 不能再分发的字符串。通常,这表示该 Port 包含专有软件,用户需要手动下载 DISTFILES,可能需要在注册软件或同意接受最终用户许可协议(EULA)的条款后进行下载。
6.5.5. RESTRICTED_FILES
当设置 RESTRICTED 或 NO_CDROM 时,此变量默认值为 ${DISTFILES} ${PATCHFILES},否则为空。如果只有部分分发文件受到限制,可以设置此变量列出它们。
6.5.6. LEGAL_TEXT
如果 Port 有上述变量未涵盖的法律问题,请将 LEGAL_TEXT 设置为解释该问题的字符串。例如,如果 FreeBSD 获得了特别许可来重新分发二进制文件,此变量必须注明这一点。
6.5.7. /usr/ports/LEGAL 和 LEGAL
设置上述任何变量的 Port 必须同时添加到 /usr/ports/LEGAL。第一列是匹配受限 distfiles 的通配符,第二列是 Port 的来源,第三列是 make -VLEGAL 的输出。
6.5.8. 示例
声明“此 Port 的 distfiles 必须手动获取”的首选方式如下:
这不仅通知用户,还在用户的机器上设置了适当的元数据,供自动化程序使用。
请注意,此段落必须在包含 bsd.port.pre.mk 后添加。
6.6. 构建机制
6.6.1. 并行构建 Port
FreeBSD 的 Ports 框架支持通过使用多个 make 子进程来进行并行构建,这使得 SMP 系统可以利用所有可用的 CPU 功率,从而加快 Port 构建的速度和效果。
这是通过将 -jX 标志传递给在供应商代码上运行的 make(1) 来实现的。这是 Port 的默认构建行为。不幸的是,并非所有 Port 都能很好地处理并行构建,因此可能需要显式禁用此功能,方法是添加 MAKE_JOBS_UNSAFE=yes 变量。当 Port 因竞争条件而导致间歇性构建失败时,就需要使用这个变量。
重要
设置
MAKE_JOBS_UNSAFE时,非常重要的一点是在 Makefile 中用注释说明,或者至少在提交信息中说明 为什么 启用时 Port 无法构建。否则,在以后提交更新时,几乎不可能修复问题或测试问题是否已经解决。
6.6.2. make、gmake 和 imake
存在几种不同的 make 实现。移植的软件通常需要特定的实现,例如 GNU make,在 FreeBSD 中称为 gmake。
如果 Port 使用 GNU make,请将 gmake 添加到 USES 中。
MAKE_CMD 可以用来引用 Port 的 Makefile 中通过 USES 设置配置的特定命令。仅在应用程序 Makefile 中的 WRKSRC 内部使用 MAKE_CMD 来调用移植软件期望的 make 实现。
如果 Port 是使用 imake 来从 Imakefile 生成 Makefile 的 X 应用程序,则应设置 USES= imake。有关更多详细信息,请参阅 使用 USES 宏中的 USES=imake 部分。
如果 Port 的源 Makefile 具有不同于 all 的主要构建目标,请相应地设置 ALL_TARGET。同样,install 和 INSTALL_TARGET 也应该如此。
6.6.3. configure 脚本
如果 Port 使用 configure 脚本从 Makefile.in 生成 Makefile,请设置 GNU_CONFIGURE=yes。要为 configure 脚本提供额外的参数(默认参数为 --prefix=${PREFIX} --infodir=${PREFIX}/${INFO_PATH} --mandir=${PREFIX}/man --build=${CONFIGURE_TARGET}),请在 CONFIGURE_ARGS 中设置这些额外的参数。可以使用 CONFIGURE_ENV 传递额外的环境变量。
GNU_CONFIGURE
Port 使用 configure 脚本进行构建准备。
HAS_CONFIGURE
与 GNU_CONFIGURE 相同,只是默认的配置目标没有添加到 CONFIGURE_ARGS 中。
CONFIGURE_ARGS
传递给 configure 脚本的额外参数。
CONFIGURE_ENV
为 configure 脚本运行设置的额外环境变量。
CONFIGURE_TARGET
重写默认的配置目标。默认值为 ${MACHINE_ARCH}-portbld-freebsd${OSREL}。
6.6.4. 使用 cmake
对于使用 CMake 的 Port,定义 USES= cmake。
CMAKE_ARGS
传递给 cmake 二进制文件的 Port 特定 CMake 标志。
CMAKE_ON
对于 CMAKE_ON 中的每个条目,都会将启用的布尔值添加到 CMAKE_ARGS 中。请参见 CMAKE_ON 和 CMAKE_OFF。
CMAKE_OFF
对于 CMAKE_OFF 中的每个条目,都会将禁用的布尔值添加到 CMAKE_ARGS 中。请参见 CMAKE_ON 和 CMAKE_OFF。
CMAKE_BUILD_TYPE
构建类型(CMake 预定义的构建配置)。默认值为 Release,如果设置了 WITH_DEBUG,则为 Debug。
CMAKE_SOURCE_PATH
源目录的路径。默认值为 ${WRKSRC}。
CONFIGURE_ENV
为 cmake 二进制文件设置的额外环境变量。
表 3. 用户可以为 cmake 构建定义的变量
CMAKE_NOCOLOR
禁用彩色构建输出。默认未设置,除非设置了 BATCH 或 PACKAGE_BUILDING。
CMake 支持以下构建配置:Debug、Release、RelWithDebInfo 和 MinSizeRel。Debug 和 Release 配置会遵循系统 *FLAGS,RelWithDebInfo 和 MinSizeRel 会分别将 CFLAGS 设置为 -O2 -g 和 -Os -DNDEBUG。CMAKE_BUILD_TYPE 的小写值会导出到 PLIST_SUB,并且如果 Port 安装 *.cmake 依赖于构建类型(参见 devel/kf5-kcrash 示例),必须使用该值。请注意,一些项目可能会定义自己的构建配置和/或通过在 CMakeLists.txt 中设置 CMAKE_BUILD_TYPE 强制特定的构建类型。为了让这样的项目的 Port 尊重 CFLAGS 和 WITH_DEBUG,必须删除这些文件中的 CMAKE_BUILD_TYPE 定义。
大多数基于 CMake 的项目支持源外构建方法。Port 的源外构建是默认设置。可以通过使用 :insource 后缀请求源内构建。在源外构建中,CONFIGURE_WRKSRC、BUILD_WRKSRC 和 INSTALL_WRKSRC 会被设置为 ${WRKDIR}/.build,并且该目录将用于存放在配置和构建阶段生成的所有文件,保持源代码目录完好。
示例 2. USES= cmake 示例
该片段演示了如何在 Port 中使用 CMake。通常不需要设置 CMAKE_SOURCE_PATH,但当源代码不在顶层目录中,或者 Port 只打算构建项目的一部分时,可以设置该值。
示例 3. CMAKE_ON 和 CMAKE_OFF
当向 CMAKE_ARGS 添加布尔值时,使用 CMAKE_ON 和 CMAKE_OFF 变量更为简便。例如:
等同于:
重要
这仅适用于
CMAKE_ARGS的默认值。OPT_CMAKE_BOOL和OPT_CMAKE_BOOL_OFF中说明的辅助工具使用相同的语义,但适用于可选值。
6.6.5. 使用 scons
如果 Port 使用 SCons,请定义 USES=scons。
为了让第三方 SConstruct 尊重传递给 SCons 的所有环境变量(即最重要的 CC/CXX/CFLAGS/CXXFLAGS),请修改 SConstruct,使得构建 Environment 如下构建:
之后,可以使用 env.Append 和 env.Replace 进行修改。
6.6.6. 使用 cargo 构建 Rust 应用程序
对于使用 Cargo 的 Port,定义 USES=cargo。
表 4. 用户可以为 cargo 构建定义的变量
CARGO_CRATES
Port 依赖的 crate 列表。每个条目需要具有 cratename-semver 的格式,例如 libc-0.2.40。Port 维护者可以通过 make cargo-crates 从 Cargo.lock 生成此列表。手动更新 crate 版本是可能的,但要注意传递依赖。如果 make cargo-crates 生成的列表很大,建议将其放在顶层 Port 目录中的 Makefile.crates 文件中。如果存在,该文件会自动被 Ports 框架引入。这有助于保持主 Port Makefile 的可管理大小。
CARGO_FEATURES
要构建的应用程序功能列表(以空格分隔)。要停用所有默认功能,请将特殊标记 --no-default-features 添加到 CARGO_FEATURES。不需要手动将其传递给 CARGO_BUILD_ARGS、CARGO_INSTALL_ARGS 和 CARGO_TEST_ARGS。
CARGO_CARGOTOML
${WRKSRC}/Cargo.toml
使用的 Cargo.toml 的路径。
CARGO_CARGOLOCK
${WRKSRC}/Cargo.lock
用于 make cargo-crates 的 Cargo.lock 的路径。必要时,可以指定多个锁定文件。
CARGO_ENV
要传递给 Cargo 的环境变量列表,类似于 MAKE_ENV。
RUSTFLAGS
传递给 Rust 编译器的标志。
CARGO_CONFIGURE
yes
使用默认的 do-configure。
CARGO_UPDATE_ARGS
在配置阶段传递给 Cargo 的额外参数。有效的参数可以通过 cargo update --help 查找。
CARGO_CARGO_BIN
${LOCALBASE}/bin/cargo
cargo 二进制文件的位置。
CARGO_BUILD
yes
使用默认的 do-build。
CARGO_BUILD_ARGS
在构建阶段传递给 Cargo 的额外参数。有效的参数可以通过 cargo build --help 查找。
CARGO_INSTALL
yes
使用默认的 do-install。
CARGO_INSTALL_ARGS
在安装阶段传递给 Cargo 的额外参数。有效的参数可以通过 cargo install --help 查找。
CARGO_INSTALL_PATH
.
要安装的 crate 的路径。这通过 --path 参数传递给 cargo install。当指定多个路径时,会多次运行 cargo install。
CARGO_TEST
yes
使用默认的 do-test。
CARGO_TEST_ARGS
在测试阶段传递给 Cargo 的额外参数。有效的参数可以通过 cargo test --help 查找。
CARGO_TARGET_DIR
${WRKDIR}/target
Cargo 输出目录的位置。
CARGO_DIST_SUBDIR
rust/crates
相对于 DISTDIR 的目录,存储 crate 分发文件。
CARGO_VENDOR_DIR
${WRKSRC}/cargo-crates
存放所有 crate 解压目录的供应商目录的位置。请尽量将其放在 PATCH_WRKSRC 下,以便于应用补丁。
CARGO_USE_GITHUB
no
启用通过 GH_TUPLE 从 GitHub 获取锁定到特定 Git 提交的 crates。这将尝试修补 WRKDIR 下的所有 Cargo.toml,以便指向离线源,而不是在构建期间从 Git 仓库获取它们。
CARGO_USE_GITLAB
no
与 CARGO_USE_GITHUB 相同,但适用于 GitLab 实例和 GL_TUPLE。
示例 4. 创建一个简单的 Rust 应用程序 Port
创建一个基于 Cargo 的 Port 是一个三阶段的过程。首先,我们需要提供一个 Port 模板来获取应用程序分发文件:
生成初始的 distinfo:
现在,分发文件已经准备好使用,我们可以继续从捆绑的 Cargo.lock 中提取 crate 依赖:
此命令的输出需要直接粘贴到 Makefile 中:
需要重新生成 distinfo 以包含所有的 crate 分发文件:
该 Port 现在已准备好进行测试构建,并可以像正常情况一样进行进一步的调整,例如创建 plist、编写说明、添加许可信息、选项等。
如果你没有在像 poudriere 这样的干净环境中测试 Port,记得在任何测试之前运行 make clean。
示例 5. 启用额外的应用程序功能
一些应用程序在其 Cargo.toml 中定义了额外的功能。可以通过在 Port 中设置 CARGO_FEATURES 来编译它们。
在这里,我们启用 Tokei 的 json 和 yaml 功能:
示例 6. 将应用程序功能编码为 Port 选项
Cargo.toml 中的一个 [features] 部分可能如下所示:
pulseaudio_backend 是默认功能,它总是启用的,除非我们显式地通过将 --no-default-features 添加到 CARGO_FEATURES 来关闭默认功能。这里,我们将 portaudio_backend 和 pulseaudio_backend 功能转化为 Port 选项:
示例 7. 列出 Crate 许可证
每个 Crate 都有自己的许可证。在为 Port 添加 LICENSE 块时,了解它们非常重要(参见 许可证)。辅助目标 cargo-crates-licenses 将尝试列出 CARGO_CRATES 中定义的所有 Crate 的许可证。
注意
make cargo-crates-licenses输出的许可证名称是 SPDX 2.1 许可证表达式,可能与 Ports 框架中定义的许可证名称不匹配。需要将它们翻译为 预定义许可证列表 中的名称。
6.6.7. 使用 meson
对于使用 Meson 的 Port,请定义 USES=meson。
表 5. 使用 meson 的 Port 变量
MESON_ARGS
要传递给 meson 二进制文件的 Port 特定 Meson 标志。
MESON_BUILD_DIR
相对于 WRKSRC 的构建目录路径。默认是 _build。
示例 8. USES=meson 示例
此代码片段演示了在 Port 中使用 Meson。
6.6.8. 构建 Go 应用程序
对于使用 Go 的 Port,定义 USES=go。请参考 go 获取可以设置的变量列表,以控制构建过程。
示例 9. 创建一个基于 Go 模块的应用程序 Port
在大多数情况下,将 GO_MODULE 变量设置为 go.mod 中 module 指令指定的值就足够了:
如果“简易”方法不适用,或者需要对依赖项进行更多控制,下面描述完整的移植过程。
创建基于 Go 的 Port 是一个五阶段的过程。首先,我们需要提供一个 Port 模板来获取应用程序分发文件:
生成初步的 distinfo 文件:
现在,分发文件已经准备好使用,我们可以提取所需的 Go 模块依赖项。此步骤需要安装 ports-mgmt/modules2tuple:
该命令的输出需要直接粘贴到 Makefile 中:
distinfo 需要重新生成,以包含所有分发文件:
现在,Port 已准备好进行测试构建,并可进行进一步调整,如创建 plist、编写说明、添加许可证信息、选项等,像平常一样进行。
如果你没有在像 poudriere 这样的干净环境中测试 Port,请记得在任何测试之前运行 make clean。
示例 10. 设置输出二进制名称或安装路径
有些 Port 需要将生成的二进制文件安装到不同的名称或路径下,而不是默认的 ${PREFIX}/bin。可以通过使用 GO_TARGET 元组语法来实现,例如:
这将把 ipfs 二进制文件安装为 ${PREFIX}/bin/ipfs-go,而
将把 dnscrypt-proxy 安装到 ${PREFIX}/sbin。
示例 11. 在模块模式下覆盖 go.mod
在获取阶段,模块感知模式(即 USES=go:modules)通过获取 Port 的 go.mod 来获取依赖包的源代码,然后立即对其运行 go mod download。由于获取阶段发生在补丁应用之前很久,files/ 中的常规补丁应用得太晚,无法影响这些依赖解析和获取步骤。
虽然目前无法通过修补上游 go.mod 来更改依赖项,但仍然可以通过将另一个 go.mod 列为第二个分发文件来 覆盖 它。
要同时覆盖 go.sum,只需将其添加到 DISTFILES 中:
6.6.9. 使用 cabal 构建 Haskell 应用程序
对于使用 Cabal 的 Ports,构建系统定义了 USES=cabal。参阅 cabal 获取可以设置的变量列表,以控制构建过程。
示例 12. 创建一个 Hackage 托管的 Haskell 应用程序的 Port
在准备一个 Haskell Cabal Port 时,必须先安装 devel/hs-cabal-install 和 ports-mgmt/hs-cabal2tuple 程序。首先,我们需要定义一些常见的 Port 变量,以便 cabal-install 获取包的分发文件:
这个最简 Makefile 使用 cabal-extract 辅助目标来获取分发文件:
现在,我们已经在 ${WRKSRC} 下得到了 ShellCheck.cabal 包说明文件,可以使用 cabal-configure 生成构建计划:
完成后,可以生成所需依赖关系的列表:
Haskell 包可能包含版本修订,就像 FreeBSD 的 Port 一样。修订仅影响 .cabal 文件。请注意 _ 后面的附加版本号。将新生成的 USE_CABAL 列表替换旧的。
最后,需要重新生成 distinfo 以包含所有分发文件:
现在,Port 已准备好进行测试构建,并可像平常一样进行进一步调整,如创建 plist、编写说明、添加许可证信息、选项等。
如果你没有在像 poudriere 这样的干净环境中测试 Port,请记得在任何测试前运行 make clean。
某些 Haskell Port 会将各种数据文件安装到 share/${PORTNAME} 下。对于此类情况,Port 侧需要进行特殊处理。Port 应定义 CABAL_WRAPPER_SCRIPTS 变量,列出将使用数据文件的每个可执行文件。此外,在少数情况下,被移植的程序使用其他 Haskell 包的数据文件,此时 FOO_DATADIR_VARS 变量会派上用场。
示例 13. 处理 Haskell Port 中的数据文件
devel/hs-profiteur 是一个 Haskell 应用程序,它生成一个包含内容的单页 HTML。
它将 HTML 模板安装到 share/profiteur 下,因此我们需要添加 CABAL_WRAPPER_SCRIPTS 选项:
该程序还尝试访问 jquery.js 文件,这是 Haskell 包 js-jquery-3.3.1 的一部分。为了能够找到该文件,我们需要使包装脚本也在 share/profiteur 中查找 js-jquery 数据文件。我们使用 profiteur_DATADIR_VARS 来实现这一点:
现在,该 Port 将把实际的二进制文件安装到 libexec/cabal/profiteur,并将脚本安装到 bin/profiteur。
除了运行程序并检查一切是否正常工作外,没有简单的方法来确定 FOO_DATADIR_VARS 选项的正确值。幸运的是,使用 FOO_DATADIR_VARS 的情况非常少见。
另一个在移植复杂的 Haskell 程序时可能遇到的特殊情况是 cabal.project 文件中存在 VCS 依赖项。
示例 14. 移植具有 VCS 依赖项的 Haskell 应用程序
net-p2p/cardano-node 是一个非常复杂的软件。在它的 cabal.project 中,有很多类似这样的块:
source-repository-package 类型的依赖项会在构建过程中自动由 cabal 拉取。不幸的是,这使得在 fetch 阶段之后需要使用网络。这是 Ports 框架不允许的。因此,这些源需要在 Port 的 Makefile 中列出。make-use-cabal 辅助目标可以使 GitHub 上托管的包更容易处理。在常规的 cabal-extract 和 cabal-configure 后运行这个目标,不仅会生成 USE_CABAL 选项,还会生成 GH_TUPLE:
将 make-use-cabal 生成的 GH_TUPLE 条目与其他条目分开可能会更有用,这样可以方便地更新 Port:
对于具有 VCS 依赖项的 Haskell Port,目前还需要以下变通方法:
6.7. 使用 GNU Autotools
如果一个 Port 需要任何 GNU Autotools 软件,添加 USES=autoreconf。有关更多信息,请参阅 autoreconf。
6.8. 使用 GNU gettext
6.8.1. 基本用法
如果 Port 需要 gettext,请设置 USES=gettext,该 Port 将继承来自 devel/gettext 的 libintl.so 依赖项。有关 gettext 用法的其他值,请参阅 USES=gettext。
一个比较常见的情况是 Port 使用 gettext 和 configure。通常,GNU configure 应该能够自动定位 gettext。
如果自动定位失败,可以通过 CPPFLAGS 和 LDFLAGS 传递 gettext 的位置,使用 localbase 如下:
6.8.2. 可选用法
一些软件产品允许禁用 NLS。例如,通过向 configure 传递 --disable-nls。在这种情况下,Port 必须根据 NLS 选项的状态有条件地使用 gettext。对于低到中等复杂度的 Port,可以使用以下惯用法:
或者使用较旧的选项方法:
接下来需要做的工作是安排使消息目录文件条件地包含在打包列表中。Makefile 部分的这个任务已经由惯用法提供。它在 高级 pkg-plist 实践 部分中进行了说明。简而言之,pkg-plist 中每个出现的 %%NLS%% 将在 NLS 被禁用时替换为 "@comment",或者在 NLS 启用时替换为空字符串。因此,如果 NLS 关闭,以 %%NLS%% 为前缀的行将在最终的打包列表中变成注释;否则,前缀将直接被省略。然后,在 pkg-plist 中每个消息目录文件路径之前插入 %%NLS%%。例如:
在高复杂度的情况下,可能需要更高级的技术,例如 动态打包列表生成。
6.8.3. 处理消息目录所在目录
有一点需要注意的是,安装消息目录文件时,目标目录必须位于 LOCALBASE/share/locale 下,并且这些目录不应由 Port 创建或删除。最常见的语言有各自的目录列在 PORTSDIR/Templates/BSD.local.dist 中。许多其他语言的目录由 devel/gettext Port 管理。请查阅其 pkg-plist 并查看该 Port 是否会为独特的语言安装消息目录文件。
6.9. 使用 Perl
如果 MASTER_SITES 设置为 CPAN,通常会自动选择正确的子目录。如果默认子目录错误,可以使用 CPAN/Module 来更改它。MASTER_SITES 也可以设置为旧的 MASTER_SITE_PERL_CPAN,然后 MASTER_SITE_SUBDIR 的首选值是顶级层次名称。例如,推荐的 p5-Module-Name 的值是 Module。可以在 cpan.org 上查看顶级层次结构。这会在模块的作者更改时保持 Port 的正常工作。
这个规则的例外情况是相关目录不存在,或者该目录中没有 distfile。在这种情况下,允许使用作者的 ID 作为 MASTER_SITE_SUBDIR。可以使用 CPAN:AUTHOR 宏,它将转换为哈希作者目录。例如,CPAN:AUTHOR 将转换为 authors/id/A/AU/AUTHOR。
当 Port 需要 Perl 支持时,必须设置 USES=perl5,并根据 perl5 USES 说明 使用可选的 USE_PERL5。
表 6. 使用 Perl 的 Port 只读变量
PERL
Perl 5 解释器的完整路径,无论是系统自带的还是从 Port 安装的,但不带版本号。当软件需要 Perl 解释器的路径时使用此变量。要替换脚本中的 "#!" 行,请使用 shebangfix。
PERL_VERSION
安装的 Perl 的完整版本(例如,5.8.9)。
PERL_LEVEL
安装的 Perl 版本,形式为 MNNNPP 的整数(例如,500809)。
PERL_ARCH
Perl 存储架构相关库的位置。默认为 ${ARCH}-freebsd。
PERL_PORT
已安装的 Perl Port 的名称(例如,perl5)。
SITE_PERL
存放特定于站点的 Perl 包的目录名称。此值会被添加到 PLIST_SUB 中。
注意
没有官方网站的 Perl 模块 Port 必须在 Makefile 的 WWW 行中链接到
cpan.org。推荐的 URL 形式是https://search.cpan.org/dist/Module-Name/(包括尾部斜杠)。
注意
不要在依赖声明中使用
${SITE_PERL}。这样做假设已经包含了 perl5.mk,但并非总是如此。如果 Port 的文件在升级过程中被移动,依赖于该 Port 的其他 Port 可能会有错误的依赖关系。正确声明 Perl 模块依赖关系的方法如下所示。
示例 15. Perl 依赖示例
对于安装手册页的 Perl Port,可以在 pkg-plist 中使用宏 PERL5_MAN3 和 PERL5_MAN1。例如,
可以替换为
注意
对于其他部分(
2和4到9)没有PERL5_MAN_x_宏,因为这些文件会安装到常规目录中。
示例 16. 仅在构建时需要 Perl 的 Port
由于默认的 USE_PERL5 值为 build 和 run,应设置为:
示例 17. 还需要 Perl 进行补丁处理的 Port
示例 18. 需要 ExtUtils::MakeMaker 来构建的 Perl 模块
大多数 Perl 模块带有 Makefile.PL 配置脚本。在这种情况下,设置:
示例 19. 需要 Module::Build 来构建的 Perl 模块
当 Perl 模块带有 Build.PL 配置脚本时,它可能需要 Module::Build,此时设置:
如果它需要的是 Module::Build::Tiny,设置:
6.10. 使用 X11
6.10.1. X.Org 组件
在 Ports 中提供的 X11 实现是 X.Org。如果应用程序依赖于 X 组件,添加 USES= xorg 并设置 USE_XORG 为所需的组件列表。完整的组件列表可以在 xorg 中找到。
Mesa 项目旨在提供免费的 OpenGL 实现。要指定对该项目的不同组件的依赖,使用 USES= gl 和 USE_GL。有关可用组件的完整列表,请参见 gl。为了向后兼容性,yes 的值会映射为 glu。
示例 20. USE_XORG 示例
USES= imake
该 Port 使用 imake。
XMKMF
如果 xmkmf 不在 PATH 中,设置为其路径。默认为 xmkmf -a。
示例 21. 使用 X11 相关变量
6.10.2. 需要 Motif 的 Port
如果 Port 需要 Motif 库,在 Makefile 中定义 USES= motif。默认的 Motif 实现是 x11-toolkits/open-motif。用户可以通过在 make.conf 中设置 WANT_LESSTIF 来选择 x11-toolkits/lesstif 作为替代实现。同样,用户也可以通过设置 WANT_OPEN_MOTIF_DEVEL 来选择 x11-toolkits/open-motif-devel。
MOTIFLIB 将由 motif.mk 设置,指向合适的 Motif 库。请修改 Port 的源代码,以便在原始 Makefile 或 Imakefile 中引用 Motif 库的位置时使用 ${MOTIFLIB}。
有两种常见情况:
如果 Port 在其 Makefile 或 Imakefile 中引用 Motif 库为
-lXm,请将其替换为${MOTIFLIB}。如果 Port 在其 Imakefile 中使用
XmClientLibs,请将其替换为${MOTIFLIB} ${XTOOLLIB} ${XLIB}。
请注意,MOTIFLIB(通常)会展开为 -L/usr/local/lib -lXm -lXp 或 /usr/local/lib/libXm.a,因此无需在前面加上 -L 或 -l。
6.10.3. X11 字体
如果 Port 安装了 X Window System 字体,请将它们放置在 LOCALBASE/lib/X11/fonts/local 中。
6.10.4. 使用 Xvfb 获取虚拟 DISPLAY
某些应用程序需要一个工作的 X11 显示器来成功编译。这对于没有图形界面的机器来说是一个问题。当使用此变量时,构建基础设施将启动虚拟帧缓冲 X 服务器。然后,工作 DISPLAY 会传递给构建过程。有关可能的参数,请参见 USES=display。
6.10.5. 桌面条目
桌面条目(Freedesktop 标准)提供了一种在安装新程序时自动调整桌面功能的方法,无需用户干预。例如,新安装的程序会自动出现在兼容的桌面环境的应用程序菜单中。桌面条目起源于 GNOME 桌面环境,但现在已经成为标准,并且可以与 KDE 和 Xfce 一起使用。这种自动化功能对用户来说是一个真正的便利,建议可以在桌面环境中使用的应用程序采用桌面条目。
6.10.5.1. 使用预定义的 .desktop 文件
包含预定义 *.desktop 文件的 Port 必须在 pkg-plist 中包含这些文件,并将它们安装到 $LOCALBASE/share/applications 目录中。INSTALL_DATA 宏 可以用来安装这些文件。
6.10.5.2. 更新桌面数据库
如果 Port 的 portname.desktop 中包含 MimeType 条目,安装和卸载后必须更新桌面数据库。为此,定义 USES= desktop-file-utils。
6.10.5.3. 使用 DESKTOP_ENTRIES 创建桌面条目
可以通过使用 DESKTOP_ENTRIES 来轻松为应用程序创建桌面条目。一个名为 name.desktop 的文件将自动创建、安装,并添加到 pkg-plist 中。语法如下:
可用的类别列表可以在 Freedesktop 网站 上找到。StartupNotify 表示该应用程序是否支持启动通知。启动通知通常是一个图形指示器,如出现在鼠标指针、菜单或面板上的时钟,表示程序正在启动。兼容启动通知的程序在启动后会清除指示器,而不兼容的程序则永远不会清除该指示器(可能会让用户困惑和恼火),因此必须将 StartupNotify 设置为 false,以便根本不显示该指示器。
示例:
DESKTOP_ENTRIES 会安装到由 DESKTOPDIR 变量指向的目录中。DESKTOPDIR 默认值为 ${PREFIX}/share/applications
6.11. 使用 GNOME
6.11.1. 介绍
本章解释了 Port 中使用的 GNOME 框架。该框架可以大致分为基础组件、GNOME 桌面组件和一些简化 Port 维护者工作的特殊宏。
6.11.2. 使用 USE_GNOME
将此变量添加到 Port 中,允许使用在 bsd.gnome.mk 中定义的宏和组件。bsd.gnome.mk 中的代码会添加所需的构建时、运行时或库依赖项,或者处理特殊文件。在 FreeBSD 中,GNOME 应用程序使用 USE_GNOME 基础设施。包括所有所需的组件,作为以空格分隔的列表。USE_GNOME 组件分为以下几个虚拟列表:基本组件、GNOME 3 组件和遗留组件。如果 Port 只需要 GTK3 库,这是定义它的最简便方式:
USE_GNOME 组件会自动添加它们所需的依赖项。有关所有 USE_GNOME 组件的详细列表,以及它们暗含的其他组件和依赖项,请参阅 GNOME 组件。
以下是一个使用了本文件中概述的许多技术的 GNOME Port 的 Makefile 示例。请将其作为创建新 Port 的指南。
注意
USE_GNOME宏没有任何参数时不会向 Port 添加任何依赖项。USE_GNOME不能在 bsd.port.pre.mk 之后设置。
6.11.3. 变量
本节解释了哪些宏是可用的,以及如何使用它们。就像在上述示例中使用的那样。更多关于 GNOME 组件的详细说明可以在 GNOME Components 中找到。必须设置 USE_GNOME 才能使这些宏生效。
GLIB_SCHEMAS 列出 Port 安装的所有 glib 模式文件。该宏会将文件添加到 Port 的 pkg-plist 中,并在安装和卸载时处理这些文件的注册。
glib 模式文件以 XML 格式编写,并以 gschema.xml 扩展名结尾。它们安装在 share/glib-2.0/schemas/ 目录下。这些模式文件包含所有应用程序配置值及其默认设置。实际由应用程序使用的数据库是通过 glib-compile-schema 构建的,该工具由 GLIB_SCHEMAS 宏运行。
注意
不要将 glib 模式文件添加到 pkg-plist 中。如果它们列在 pkg-plist 中,则不会被注册,应用程序可能无法正常工作。
GCONF_SCHEMAS 列出所有 gconf 模式文件。该宏会将模式文件添加到 Port 的 pkg-plist 中,并在安装和卸载时处理这些文件的注册。
GConf 是几乎所有 GNOME 应用程序用于存储设置的基于 XML 的数据库。这些文件安装在 etc/gconf/schemas 目录下。该数据库由已安装的模式文件定义,这些文件用于生成 %gconf.xml 键文件。每个由 Port 安装的模式文件都必须在 Makefile 中有一个条目:
注意
GConf 模式文件应该列在
GCONF_SCHEMAS宏中,而不是 pkg-plist 中。如果它们列在 pkg-plist 中,则不会被注册,应用程序可能无法正常工作。
6.12. GNOME 组件
要获得更多有关 GNOME Port 的帮助,可以参考一些 现有的 Port 示例。如果需要更多帮助,访问 FreeBSD GNOME 页面 查找联系信息。这些组件分为当前正在使用的 GNOME 组件和旧版组件。如果组件支持参数,它们将列在说明中的括号中。第一个参数为默认值。如果组件默认添加到构建和运行依赖项中,则会显示“同时用于构建和运行”。
atk
accessibility/atk
辅助工具包 (ATK)
atkmm
accessibility/atkmm
atk 的 C++ 绑定
cairo
graphics/cairo
支持跨设备输出的矢量图形库
cairomm
graphics/cairomm
cairo 的 C++ 绑定
dconf
devel/dconf
配置数据库系统(同时用于构建和运行)
evolutiondataserver3
databases/evolution-data-server
Evolution 集成邮件/PIM 套件的数据后端
gdkpixbuf2
graphics/gdk-pixbuf2
GTK+ 图形库
glib20
devel/glib20
GNOME 核心库 glib20
glibmm
devel/glibmm
glib20 的 C++ 绑定
gnomecontrolcenter3
sysutils/gnome-control-center
GNOME 3 控制中心
gnomedesktop3
x11/gnome-desktop
GNOME 3 桌面 UI 库
gsound
audio/gsound
用于播放系统声音的 GObject 库(同时用于构建和运行)
gtk-update-icon-cache
graphics/gtk-update-icon-cache
来自 Gtk+ 工具包的 Gtk-update-icon-cache 工具
gtk20
x11-toolkits/gtk20
Gtk+ 2 工具包
gtk30
x11-toolkits/gtk30
Gtk+ 3 工具包
gtkmm20
x11-toolkits/gtkmm20
gtk20 工具包的 C++ 绑定 2.0
gtkmm24
x11-toolkits/gtkmm24
gtk20 工具包的 C++ 绑定 2.4
gtkmm30
x11-toolkits/gtkmm30
gtk30 工具包的 C++ 绑定 3.0
gtksourceview2
x11-toolkits/gtksourceview2
为 GtkTextView 添加语法高亮的组件
gtksourceview3
x11-toolkits/gtksourceview3
为 GtkTextView 组件添加语法高亮的文本组件
gtksourceviewmm3
x11-toolkits/gtksourceviewmm3
gtksourceview3 库的 C++ 绑定
gvfs
devel/gvfs
GNOME 虚拟文件系统
intltool
textproc/intltool
国际化工具(另见 intlhack)
introspection
devel/gobject-introspection
基本的 introspection 绑定和生成 introspection 绑定的工具。大多数时候 :build 足够了,:both/:run 仅在应用程序使用 introspection 绑定时需要。(同时用于构建和运行)
libgda5
databases/libgda5
提供对不同数据源的统一访问
libgda5-ui
databases/libgda5-ui
来自 libgda5 库的 UI 库
libgdamm5
databases/libgdamm5
libgda5 库的 C++ 绑定
libgsf
devel/libgsf
处理结构化文件格式的可扩展 I/O 抽象
librsvg2
graphics/librsvg2
用于解析和渲染 SVG 矢量图形文件的库
libsigc++20
devel/libsigc++20
C++ 的回调框架
libxml++26
textproc/libxml++26
libxml2 库的 C++ 绑定
libxml2
textproc/libxml2
XML 解析库(同时用于构建和运行)
libxslt
textproc/libxslt
XSLT C 库(同时用于构建和运行)
metacity
x11-wm/metacity
GNOME 的窗口管理器
nautilus3
x11-fm/nautilus
GNOME 文件管理器
pango
x11-toolkits/pango
用于国际化文本的布局和渲染的开源框架
pangomm
x11-toolkits/pangomm
pango 库的 C++ 绑定
py3gobject3
devel/py3-gobject3
Python 3,GObject 3.0 绑定
pygobject3
devel/py-gobject3
Python 2,GObject 3.0 绑定
vte3
x11-toolkits/vte3
带有改进的可访问性和国际化支持的终端组件
6.12.1. GNOME 宏组件
gnomeprefix
为 configure 提供一些默认的路径。
intlhack
与 intltool 相同,但进行了修补,以确保使用 share/locale/。仅在 intltool 不足时使用。
referencehack
该宏用于帮助将 API 或参考文档拆分为自己的 Port。
6.12.2. GNOME 旧版组件
atspi
accessibility/at-spi
辅助技术服务提供者接口
esound
audio/esound
Enlightenment 声音包
gal2
x11-toolkits/gal2
来自 GNOME 2 gnumeric 的组件
gconf2
devel/gconf2
GNOME 2 的配置数据库系统
gconfmm26
devel/gconfmm26
gconf2 的 C++ 绑定
gdkpixbuf
graphics/gdk-pixbuf
GTK+ 图形库
glib12
devel/glib12
glib 1.2 核心库
gnomedocutils
textproc/gnome-doc-utils
GNOME 文档工具
gnomemimedata
misc/gnome-mime-data
GNOME 2 的 MIME 和应用程序数据库
gnomesharp20
x11-toolkits/gnome-sharp20
GNOME 2 接口,用于 .NET 运行时
gnomespeech
accessibility/gnome-speech
GNOME 2 的语音合成 API
gnomevfs2
devel/gnome-vfs
GNOME 2 虚拟文件系统
gtk12
x11-toolkits/gtk12
Gtk+ 1.2 工具包
gtkhtml3
www/gtkhtml3
轻量级 HTML 渲染/打印/编辑引擎
gtkhtml4
www/gtkhtml4
轻量级 HTML 渲染/打印/编辑引擎
gtksharp20
x11-toolkits/gtk-sharp20
用于 .NET 运行时的 GTK+ 和 GNOME 2 接口
gtksourceview
x11-toolkits/gtksourceview
为 GtkTextView 添加语法高亮的组件
libartgpl2
graphics/libart_lgpl
高性能 2D 图形库
libbonobo
devel/libbonobo
GNOME 2 的组件和复合文档系统
libbonoboui
x11-toolkits/libbonoboui
GNOME 2 libbonobo 组件的 GUI 前端
libgda4
databases/libgda4
提供对不同数据源的统一访问
libglade2
devel/libglade2
GNOME 2 glade 库
libgnome
x11/libgnome
GNOME 2 库,GNU 桌面环境
libgnomecanvas
graphics/libgnomecanvas
GNOME 2 图形库
libgnomekbd
x11/libgnomekbd
GNOME 2 键盘共享库
libgnomeprint
print/libgnomeprint
GNOME 2 打印支持库
libgnomeprintui
x11-toolkits/libgnomeprintui
GNOME 2 打印支持库
libgnomeui
x11-toolkits/libgnomeui
GNOME 2 GUI 库,GNU 桌面环境
libgtkhtml
www/libgtkhtml
轻量级 HTML 渲染/打印/编辑引擎
libgtksourceviewmm
x11-toolkits/libgtksourceviewmm
GtkSourceView 的 C++ 绑定
libidl
devel/libIDL
用于创建 CORBA IDL 文件树的库
libsigc++12
devel/libsigc++12
C++ 的回调框架
libwnck
x11-toolkits/libwnck
用于编写分页器和任务列表的库
libwnck3
x11-toolkits/libwnck3
用于编写分页器和任务列表的库
orbit2
devel/ORBit2
高性能 CORBA ORB,支持 C 语言
pygnome2
x11-toolkits/py-gnome2
GNOME 2 的 Python 绑定
pygobject
devel/py-gobject
Python 2,GObject 2.0 绑定
pygtk2
x11-toolkits/py-gtk2
GTK+ 的 Python 绑定
pygtksourceview
x11-toolkits/py-gtksourceview
GtkSourceView 2 的 Python 绑定
vte
x11-toolkits/vte
带有改进的可访问性和国际化支持的终端组件
表 11. 废弃组件:请勿使用
pangox-compat
pangox-compat 已被废弃,并从 pango 包中分离出来。
6.13. 使用 Qt
注意
有关 Qt 本身的一些 Port,请参阅
qt-dist。
6.13.1. 需要 Qt 的 Port
Ports 提供了对 Qt 5 和 Qt 6 的支持,分别通过 USES+=qt:5 和 USES+=qt:6。将 USE_QT 设置为所需的 Qt 组件(库、工具、插件)列表。
Qt 框架导出了一些可以供 Port 使用的变量,下面列出了一些:
表 12. 使用 Qt 的 Port 提供的变量
QMAKE
qmake 可执行文件的完整路径。
LRELEASE
lrelease 工具的完整路径。
MOC
moc 的完整路径。
RCC
rcc 的完整路径。
UIC
uic 的完整路径。
QT_INCDIR
Qt 的包含目录。
QT_LIBDIR
Qt 的库路径。
QT_PLUGINDIR
Qt 的插件路径。