---
title: 第 6 章 特殊情况
prev: books/porters-handbook/makefile
next: books/porters-handbook/plist
showBookMenu: true
weight: 6
params:
  path: "/books/porters-handbook/special/"
---

[[special]]
= 特殊情况
:doctype: book
:toc: macro
:toclevels: 1
:icons: font
:sectnums:
:sectnumlevels: 6
:sectnumoffset: 6
:partnums:
:source-highlighter: rouge
:experimental:
:images-path: books/porters-handbook/

ifdef::env-beastie[]
ifdef::backend-html5[]
:imagesdir: ../../../../images/{images-path}
endif::[]
ifndef::book[]
include::shared/authors.adoc[]
include::shared/mirrors.adoc[]
include::shared/releases.adoc[]
include::shared/attributes/attributes-{{% lang %}}.adoc[]
include::shared/{{% lang %}}/teams.adoc[]
include::shared/{{% lang %}}/mailing-lists.adoc[]
include::shared/{{% lang %}}/urls.adoc[]
toc::[]
endif::[]
ifdef::backend-pdf,backend-epub3[]
include::../../../../../shared/asciidoctor.adoc[]
endif::[]
endif::[]

ifndef::env-beastie[]
toc::[]
include::../../../../../shared/asciidoctor.adoc[]
endif::[]

有一些您在创建port时的特殊情况，我们在这里提一下。

[[porting-shlibs]]
== 共享库

如果您的port安装了一个或多个共享库,那么请定义一个 `USE_LDCONFIG` make 变量， 在``post-install``标记把它注册进共享库 缓冲时会调用[.filename]##bsd.port.mk##去运行 ``${LDCONFIG} -m``来指向新库的安装目录。 (通常是 [.filename]##PREFIX/lib##) 同样，您也可以适当的在您的 [.filename]##pke-plist##文件 中定义一组``@exec /sbin/ldconfig -m`` 和``@unexec /sbin/ldconfig -R，`` 那么用户可以在安装后马上 就能使用，并且在卸载软件包后系统也不会认为这些共享库仍然存在。

[.programlisting]
....
USE_LDCONFIG= yes
....

如果您需要把共享库安装在缺省的位置之外， 可以通过定义 make 变量 `USE_LDCONFIG` 来改变默认的安装路径， 它包含安装共享库的目录列表 例如： 如果您的共享库安装到 [.filename]#PREFIX/lib/foo# 和 [.filename]#PREFIX/lib/bar# directories目录，您可以在您的 [.filename]##Makefile##中这样设置:

[.programlisting]
....
USE_LDCONFIG= ${PREFIX}/lib/foo ${PREFIX}/lib/bar
....

请务必仔细检查， 通常这是完全不必要的， 或者可以通过 `-rpath` 或在连接时设置 `LD_RUN_PATH` 来避免 (参见 package:lang/moscow_ml[] 给出的例子)， 或者用一个 shell 封装程序来在执行可执行文件之前设置 `LD_LIBRARY_PATH`， 类似 package:www/seamonkey[] 那样。

当在 64-位系统上安装 32-位 的函数库时， 请使用 `USE_LDCONFIG32`。

尽量将共享库版本号保持为 [.filename]#libfoo.so.0# 这样的格式。 我们的运行环境连接器只会检查主 (第一个) 版本数字。

如果在更新 port 时升级了其库的主版本号， 则其它所有连接了受影响的库的 port 的 `PORTREVISION` 都应递增， 以强制它们采用新版本的库重新编译。

[[porting-restrictions]]
== Ports 的发行限制

众多协议，并且其中的一些致力于 限制怎样的应用程序能被打包， 是否能用于销售赢利等等。

[IMPORTANT]
====
做为一名porter您有义务去阅读软件的协议 并且确保FreeBSD 项目不必为通过FTP/HTTP 或CD-ROM重新发布源码或编译的二进制而解释 什么。如果有任何疑问， 请联系 {freebsd-ports}。
====

处于这种情况，就可以设置以下描述 的变量。

=== `NO_PACKAGE` (禁止编译结果打包)

这个变量表示我们可能不能生成这个应用 程序的二进制文件。例如，他的协议不允许 二进制文件的再次发行，或者他可能禁止从 补丁过的源代码打包的发行。

不管怎么样，port的 `DISTFILES` 可以 随意的镜像到FTP/HTTP。除非``NO_CDROM`` 变量也被设置，软件包也可以发行在一张CD-ROM （或类似的媒介上）。

``NO_PACKAGE``也能用在当二进制包 不是非常有用，并且这个应用软件经常要 从源代码编译。例如：当这个应用软件在 编译的时候要在配置信息中指定特定的硬件 代码时，可以设置``NO_PACKAGE``。

``NO_PACKAGE``应该设置成字符串 来描述为什么这个软件 不能打包。

=== `NO_CDROM` (禁止以 CDROM 发行预编译包)

这个变量仅仅指出虽然我们允许 生成二进制包，但也许我们既不能把这个 软件包也不能把port的``DISTFILES`` 放在光盘（或类似的媒介）上销售。但不管怎么样， 二进制包和port的``DISTFILES`` 可以从FTP/HTTP上获得。

如果这个变量和 ``NO_PACKAGE``一起被设置， 那么这个port的``DISTFIELS`` 将只能从FTP/HTTP上获得。

`NO_CDROM` 应该被设置成一个字符串 来描述为什么这个port不能重新发布在CD-ROM上。 例如：如果这个port的协议仅仅是用于"非商业活动" ,那么这个变量就能设置了。

=== `NOFETCHFILES` (不自动抓取指定的文件)

在 `NOFETCHFILES` 变量中定义的文件， 不会自动从 `MASTER_SITES` 抓取。 一种典型的用例是， 使用来自某个软件供应商提供的 CD-ROM 上的文件。

用于检查在 `MASTER_SITES` 上是否包含了所需文件的工具， 应忽略这些文件， 而不是报告它们不存在。

=== `RESTRICTED` (禁止任何形式的再分发)

如果应用程序既不允许镜像其 `DISTFILES`， 也不允许发布其预编译版本的包， 设置它就可以了。

`NO_CDROM` 或 `NO_PACKAGE` 不应与 `RESTRICTED` 同时设置， 因为它包含了这些情形。

`RESTRICTED` 应设置为一个说明 port 为何不能发布的串。 典型情况可能是由于 port 包含了专有的软件， 因而用户需要自行下载 `DISTFILES`， 可能是注册或者同意某一 EULA 的条款。

=== `RESTRICTED_FILES` (禁止某些文件的再分发)

当设置了 `RESTRICTED` 或 `NO_CDROM` 时， 这个变量会默认设置为 `${DISTFILES} ${PATCHFILES}`， 否则它会为空。 如果只有某些源码包文件是受限的， 则可以用这个变量来指明它们。

注意， port committer 应该在 [.filename]#/usr/ports/LEGAL# 中为每一个源码包文件撰写对应的项目， 并介绍这些限制的原因。

[[building]]
== 联编机制

[[parallel-builds]]
=== Ports 的并行联编

FreeBSD ports 框架支持使用多个 `make` 子进程来进行并行编译， 在 SMP 上这可以全面地利用系统的 CPU 计算能力， 令 port 的联编过程更快、 更有效率。

目前这是通过向原作者的代码传递 man:make[1] 参数 `-jX` 来实现的。 遗憾的是， 并不是所有的 port 都能够很好地处理这个选项。 因此， 必须通过明确地在 [.filename]#Makefile# 中指定 `MAKE_JOBS_SAFE=yes` 来启用这一功能。

从 port 监护人的角度还有一个控制的方法是设置 `MAKE_JOBS_UNSAFE=yes` 变量。 这个变量主要是用于已知不能与 `-jX` 配合使用的 port， 即使用户在 [.filename]#/etc/make.conf# 中定义了 `FORCE_MAKE_JOBS=yes` 变量， 系统也不会使用并行编译。

[[using-make]]
=== `make`、 `gmake`， 以及 `imake`

如果 port 用到了 GNU make， 应设置 `USE_GMAKE=yes`。

.与 gmake 有关的 port 变量
[cols="1,1", frame="none", options="header"]
|===
| 变量
| 意义

|`USE_GMAKE`
|此 port 需要使用 `gmake` 来完成联编过程。

|`GMAKE`
|不在 `PATH` 中时， `gmake` 的完整路径。
|===

对于 X 应用程序的 port， 如果它使用 imake 根据 [.filename]#Imakefile# 文件来生成 [.filename]#Makefile#， 则应设置 `USE_IMAKE=yes`。 这会使联编过程中的配置 (configure) 阶段自动执行 `xmkmf -a`。 如果 `-a` 标志会给您的 port 带来麻烦， 则需设置 `XMKMF=xmkmf`。 如果 port 用到了 imake 但并不使用 `install.man` target， 则应设置 `NO_INSTALL_MANPAGES=yes`。

如果 port 源文件的 [.filename]#Makefile# 的主联编 target 是 `all` 以外的名字， 应对应地设置 `ALL_TARGET`。 对于 `install` 而言， 对应的变量是 `INSTALL_TARGET`。

[[using-configure]]
=== `configure` 脚本

假如 port 使用 `configure` 脚本来从 [.filename]#Makefile.in# 生成 [.filename]#Makefile# 文件， 需要设置 `GNU_CONFIGURE=yes`。 如果希望传额外的参数给 `configure` 脚本 (默认参数为 `--prefix=${PREFIX} --infodir=${PREFIX}/${INFO_PATH} --mandir=${MANPREFIX}/man --build=${CONFIGURE_TARGET}`)， 应通过 `CONFIGURE_ARGS` 来指定这些参数。 类似地， 可以通过 `CONFIGURE_ENV` 变量来传递一些环境变量。

如果您的软件包使用 GNU `configure`， 而生成的可执行文件命名方式 "怪异" 如 [.filename]#i386-portbld-freebsd4.7-#_应用程序名_， 则需要更进一步地通过改变 `CONFIGURE_TARGET` 变量来按照较新版本的 `autoconf` 生成的脚本所希望的方式指定 target。 其方法是， 紧随 [.filename]#Makefile# 中 `GNU_CONFIGURE=yes` 一行之后加入：

`CONFIGURE_TARGET=--build=${MACHINE_ARCH}-portbld-freebsd${OSREL}`

.用于用到了 `configure` 脚本的 port 的变量
[cols="1,1", frame="none", options="header"]
|===
| 变量
| 意义

|`GNU_CONFIGURE`
|此 port 需要用 `configure` 脚本来准备联编。

|`HAS_CONFIGURE`
|与 `GNU_CONFIGURE` 类似， 但默认的 configure target 并不加入 `CONFIGURE_ARGS`。

|`CONFIGURE_ARGS`
|希望传给 `configure` 脚本的额外参数。

|`CONFIGURE_ENV`
|希望在执行 `configure` 脚本时设置的环境变量。

|`CONFIGURE_TARGET`
|替换默认的 configure target。 其默认值是 `${MACHINE_ARCH}-portbld-freebsd${OSREL}`。
|===

[[using-scons]]
=== 使用 `scons`

如果您的 port 使用 SCons， 就需要定义 `USE_SCONS=yes` 了。

.使用 `scons` 的 port 会用到的变量
[cols="1,1", frame="none", options="header"]
|===
| 变量
| 含义

|`SCONS_ARGS`
|当前 port 希望传给 SCons 环境的参数。

|`SCONS_BUILDENV`
|希望在系统环境中设置的变量。

|`SCONS_ENV`
|希望在 SCons 环境中设置的变量。

|`SCONS_TARGET`
|传递给 SCons 的最后一个参数， 类似于 `MAKE_TARGET`。
|===

如果希望让第三方的 [.filename]#SConstruct# 尊重通过 `SCONS_ENV` (其中最重要的是 `CC/CXX/CFLAGS/CXXFLAGS` 配置) 传给 Scons 的配置， 则需要对 [.filename]#SConstruct# 进行修改， 使联编的 `Environment` 按下列方式建立：

[.programlisting]
....
env = Environment(**ARGUMENTS)
....

其后， 可以通过 `env.Append` 和 `env.Replace` 来对它进行修改。

[[using-autotools]]
== 利用 GNU autotools

[[using-autotools-introduction]]
=== 入门

众多 GNU autotools 提供了一种在多重操作系统和机器架构之上联编软件的抽象机制。 在 Ports Collection 中， port 可以通过简单的方法来使用这些工具：

[.programlisting]
....
USE_AUTOTOOLS= 工具:版本[:操作] ...
....

撰写本书时， _工具_ 可以设置为 `libtool`、 `libltdl`、 `autoconf`、 `autoheader`、 `automake` 或 `aclocal` 之一。

_版本_ 用来指定希望使用的工具的特定版本 (参见 `devel/{automake,autoconf,libtool}[0-9]+` 以了解有效的版本号)。

_操作_ 是一个可选的扩展选项， 用于修改如何使用工具。

可以同时指定多个不同的工具， 可以在一行中指定， 也可以用 Makefile 的 `+=` 结构。

最后， 可以使用一个特殊的名为 `autotools` 的工具， 它会安装全部可用的 autotools 版本， 以适应跨平台开发的需要。 您可以通过安装 `devel/autotools` port 来达到这一目的。

[[using-libtool]]
=== `libtool`

使用 GNU 联编框架的共享库通常会使用 `libtool` 来调整共享库的编译和安装， 以便与所运行的操作系统相匹配。 通常的做法是使用应用程序所附带的 `libtool` 副本。 如果需要使用外部的 `libtool`， 则可以使用 Ports 套件提供的版本：

[.programlisting]
....
USE_AUTOTOOLS= libtool:版本[:env]
....

如果不使用额外的操作符， `libtool:版本` 表示希望联编框架使用 configure 脚本来对系统所安装的 `libtool` 进行修补。 这会暗含地定义 `GNU_CONFIGURE`。 更进一步， 联编框架还会设置一系列 make 和 shell 变量用于 port 后续的操作。 请参见 [.filename]#bsd.autotools.mk# 了解进一步的详情。

如果指定了 `:env` 操作符， 则表示只设置环境， 而跳过其他的操作。

最后， `LIBTOOLFLAGS` 和 `LIBTOOLFILES` 可以用来替换最常修改的参数， 以及将被 `libtool` 修补的文件。 多数 port 不需要这样做。 请参见 [.filename]#bsd.autotools.mk# 以了解进一步的细节。

[[using-libltdl]]
=== `libltdl`

一些 ports 会使用 `libltdl` 库， 后者是 `libtool` 软件包的一部分。 使用这个库并不意味着必须使用 `libtool` 本身， 因此提供了另一组结构。

[.programlisting]
....
USE_AUTOTOOLS= libltdl:版本
....

目前， 这一设置所做的全部工作是将 `LIB_DEPENDS` 设置为适当的 `libltdl` port， 并作为一项方便的功能， 协助开发人员消除在 `USE_AUTOTOOLS` 框架以外的， 对于 autotools port 的依赖。 这个工具并不提供其它的操作符。

[[using-autoconf]]
=== `autoconf` 和 `autoheader`

某些 port 并没有直接提供 configure 脚本， 但包含了作为 autoconf 模板的 [.filename]#configure.ac# 文件。 可以用下列设置来要求 `autoconf` 创建 configure 脚本， 并使用 `autoheader` 来为 configure 脚本创建模板头文件。

[.programlisting]
....
USE_AUTOTOOLS=	autoconf:版本[:env]
....

以及

[.programlisting]
....
USE_AUTOTOOLS=	autoheader:版本
....

上述设置会暗含使用 `autoconf:版本`。

对于 `libtool`， 设置与前面类似。 如果指定可选的 `:env` 操作符， 则表示只设置用于后续工作的环境。 如果不指定， 则会对 port 进行相应的修补和重新配置。

其它的可选变量， 如 `AUTOCONF_ARGS` 和 `AUTOHEADER_ARGS` 可以通过 port 的 [.filename]#Makefile# 来显式地指定替换。 类似 `libtool`， 多数 port 并不需要这样做。

[[using-automake]]
=== `automake` 和 `aclocal`

某些软件包只提供了 [.filename]#Makefile.am# 文件。 这些文件必须首先用 `automake` 转换为 [.filename]#Makefile.in# 并使用 `configure` 来生成实际的 [.filename]#Makefile#。

类似地， 偶尔会有一些软件包不提供联编所需的 [.filename]#aclocal.m4# 文件。 这些文件可以通过使用 `aclocal` 来扫描 [.filename]#configure.ac# 或 [.filename]#configure.in# 自动生成。

`aclocal` 与 `automake` 有和 `autoheader` 与 `autoconf` 在前面一节中所介绍的相类似的关系。 `aclocal` 会暗含使用 `automake`， 因此：

[.programlisting]
....
USE_AUTOTOOLS=	automake:版本[:env]
....

和

[.programlisting]
....
USE_AUTOTOOLS=	aclocal:版本
....

也自动暗含使用 `automake:版本`。

与 `libtool` 类似， `autoconf` 如果使用了可选的 `:env` 操作符表示仅仅设置用于后续使用的环境， 如果不设置， 则会对 port 进行重新配置。

对于 `autoconf` 和 `autoheader` 而言， `automake` 和 `aclocal` 提供了对应的可选参数变量 `AUTOMAKE_ARGS` 和 `ACLOCAL_ARGS`， 如果需要的话， 可以在 port 的 [.filename]#Makefile# 中指定。

[[using-gettext]]
== 使用 GNU `gettext`

=== 基本用法

如果您的 port 需要使用 `gettext`， 只要将 `USE_GETTEXT` 设置为 `yes`， 您的 port 就会增加对 package:devel/gettext[] 的依赖。 `USE_GETTEXT` 也可以指定为所需的 `libintl` 库的版本， 它是 `gettext` 的基本组成部分， 尽管如此， _强烈建议您不要_ 使用这个功能： 您的 port 应能与目前版本的 package:devel/gettext[] 配合工作。

在 port 中相当常见的情况下， 会需要同时使用 `gettext` 和 `configure`。 一般而言， GNU `configure` 能够自动定位到 `gettext`。 如果它没有成功地完成这项工作， 则可以通过类似下面这样的 `CPPFLAGS` 和 `LDFLAGS` 将 `gettext` 的位置告诉它：

[.programlisting]
....
USE_GETTEXT=    yes
CPPFLAGS+=      -I${LOCALBASE}/include
LDFLAGS+=       -L${LOCALBASE}/lib

GNU_CONFIGURE=  yes
CONFIGURE_ENV=  CPPFLAGS="${CPPFLAGS}" \
                LDFLAGS="${LDFLAGS}"
....

当然， 不需要传参数给 `configure` 时， 代码可以更为简练：

[.programlisting]
....
USE_GETTEXT=    yes
GNU_CONFIGURE=  yes
CONFIGURE_ENV=  CPPFLAGS="-I${LOCALBASE}/include" \
                LDFLAGS="-L${LOCALBASE}/lib"
....

=== 可选用法

一些软件产品提供了禁用 NLS 的能力， 例如， 在 `configure` 时， 指定 `--disable-nls` 参数。 如果您 port 的软件支持这种配置， 则应根据 <<knobs-without-nls,`WITHOUT_NLS`>> 的设置来有条件地使用 `gettext`。 对于比较简单和不太复杂的 port， 您可以使用下列结构：

[.programlisting]
....
GNU_CONFIGURE=          yes

.if !defined(WITHOUT_NLS)
USE_GETTEXT=            yes
PLIST_SUB+=             NLS=""
.else
CONFIGURE_ARGS+=        --disable-nls
PLIST_SUB+=             NLS="@comment "
.endif
....

您要做的下一件事是合理地安排装箱单文件， 使其根据用户配置来决定是否将消息编录 (message catalog) 文件放入最终的装箱单。 前面已经介绍了在 [.filename]#Makefile# 中所需的写法， 这种做法在 crossref:plist[plist-sub,高级 [.filename]#pkg-plist# 用法] 这节中进行了介绍。 简单地说， 在 [.filename]#pkg-plist# 中出现的 ``%%NLS%%`` 均会在禁用 NLS 时自动替换为 "``@comment ``"， 反之则替换为空串。 这样， 在最终的装箱单中带 ``%%NLS%%`` 的行， 在 NLS 关闭的情况下就会变为注释， 反之， 这些前缀就会自动删掉。 现在需要做的事情就是把 ``%%NLS%%`` 插到 [.filename]#pkg-plist# 中的消息编录文件的那些行开头， 例如：

[.programlisting]
....
%%NLS%%share/locale/fr/LC_MESSAGES/foobar.mo
%%NLS%%share/locale/no/LC_MESSAGES/foobar.mo
....

在比较复杂的情形中， 您可能需要使用更高级的技术， 例如 crossref:plist[plist-dynamic,动态生成装箱单] 等。

=== 处理消息编录目录

在安装消息编录文件时还有一个需要注意的地方。 这些文件会放到 [.filename]#LOCALBASE/shared/locale# 下与语言对应的目录中， 这些目录一般您的 port 不需要创建和删除。 最常用的语言的目录已经在 [.filename]#/etc/mtree/BSD.local.dist# 中列出； 也就是说， 它们是基本系统的一部分。 其他一些语言的目录， 则由 package:devel/gettext[] 控制。 您最好查看一下 [.filename]#pkg-plist#， 以确定是否正在安装某种不常用语言的文件。

[[using-perl]]
== 使用 `perl`

如果 `MASTER_SITES` 设为 `MASTER_SITE_PERL_CPAN`， 则应尽量把 `MASTER_SITE_SUBDIR` 设置为顶级目录的名字。 例如， 对 `p5-Module-Name` 而言推荐的名字是 `Module`。 您可以在 http://cpan.org/modules/by-module/[cpan.org] 找到顶级目录的名字。 这可以确保在模块的作者发生变化时， 保持 port 继续可用。

以上规则有一个例外， 即对应目录不存在或源码包不在那个目录中时， 允许使用作者的 id 作为 `MASTER_SITE_SUBDIR`。

所有这些选项均同时接受 `YES` 和版本串， 类似 `5.8.0+` 这样的写法。 使用 `YES` 表示 port 能够配合所有受支持的 Perl 版本来使用。 如果 port 只能配合特定版本的 Perl 来使用， 则可以用版本串来表示， 例如最低版本 (如 `5.7.3+`)、 最高版本 (如 `5.8.0-`) 或某个具体的版本 (如 `5.8.3`)。

.用于用到 `perl` 的 port 的变量
[cols="1,1", frame="none", options="header"]
|===
| 变量
| 意义

|`USE_PERL5`
|表示 port 将 `perl 5` 用于联编和运行。

|`USE_PERL5_BUILD`
|表示 port 将 `perl 5` 用于联编。

|`USE_PERL5_RUN`
|表示 port 将 `perl 5` 用于运行。

|`PERL`
|`perl 5` 的完整路径， 可能是系统自带的， 或者从 port 安装， 但没有版本号。 如果您需要在脚本中替换 "`#!`" 行， 则应使用这个变量。

|`PERL_CONFIGURE`
|采用 Perl 的 MakeMaker 进行配置。 这一变量隐含设置 `USE_PERL5`。

|`PERL_MODBUILD`
|使用 Module::Build 进行配置、 联编并安装。 这一变量隐含设置 `PERL_CONFIGURE`。
|===

[NOTE]
====
Perl 模块通常并没有官方网站， 这些 port 应将 `cpan.org` 作为其 [.filename]#pkg-descr# WWW 行的内容。 推荐的 URL 格式为 `http://search.cpan.org/dist/Module-Name/` (保留最后的斜线)。
====

[[using-x11]]
== 使用 X11

[[x11-variables]]
=== X.Org 组件

在 Ports 套件中提供的 X11 实现是 X.Org。 如果您的应用程序用到了 X 组件， 则应将 `USE_XORG` 设为所需要的那些组件。 目前可用的组件包括：

`bigreqsproto compositeproto damageproto dmx dmxproto evieproto fixesproto fontcacheproto fontenc fontsproto fontutil glproto ice inputproto kbproto libfs oldx printproto randrproto recordproto renderproto resourceproto scrnsaverproto sm trapproto videoproto x11 xau xaw xaw6 xaw7 xaw8 xbitmaps xcmiscproto xcomposite xcursor xdamage xdmcp xevie xext xextproto xf86bigfontproto xf86dgaproto xf86driproto xf86miscproto xf86rushproto xf86vidmodeproto xfixes xfont xfontcache xft xi xinerama xineramaproto xkbfile xkbui xmu xmuu xorg-server xp xpm xprintapputil xprintutil xpr oto xproxymngproto xrandr xrender xres xscrnsaver xt xtrans xtrap xtst xv xvmc xxf86dga xxf86misc xxf86vm`.

最新的列表， 可以在 [.filename]#/usr/ports/Mk/bsd.xorg.mk# 中找到。

The Mesa Project 是一个致力于自由的 OpenGL 实现的计划。 您可以使用 `USE_GL` 变量来让 port 依赖其不同的组件。 可用的选项包括： `glut, glu, glw, glew, gl` 和 `linux`。 为了实现向前兼容， 当使用 `yes` 时系统会自动将其映射为 `glu`。

[[use-xorg-example]]
.使用 USE_XORG 的例子
[example]
====
[.programlisting]
....
USE_XORG=   xrender xft xkbfile xt xaw
USE_GL=     glu
....

====

许多 ports 会定义 `USE_XLIB`， 这会导致 port 依赖 50 多个动态连接库。 由于它出现于 X.org 模块化之前， 因此这个变量仅为向前兼容的原因提供， 新的 port 不应再使用它。

.用到 X 的 port 可以使用的变量
[cols="1,1", frame="none"]
|===
|`USE_XLIB`
|此 port 用到了 X 库。 已过时 - 您应使用 `USE_XORG` 变量列出用到的 X.Org 组件， 而不是使用这个变量。

|`USE_IMAKE`
|此 port 用到了 `imake`。

|`USE_X_PREFIX`
|已过时。 目前其作用与 `USE_XLIB` 相同， 并可以直接用后者替换。

|`XMKMF`
|设置为 `xmkmf` 的完整路径名， 如果它不在 `PATH` 中的话。 默认值是 `xmkmf -a`。
|===

.用于表示对 X11 某些组件的依赖关系的变量
[cols="1,1", frame="none"]
|===
|`X_IMAKE_PORT`
|用以提供 `imake` 以及许多其它用于联编 X11 的工具的 port。

|`X_LIBRARIES_PORT`
|用以提供 X11 库的 port。

|`X_CLIENTS_PORT`
|用以提供 X 客户的 port。

|`X_SERVER_PORT`
|用以提供 X 服务的 port。

|`X_FONTSERVER_PORT`
|用以提供字体服务的 port。

|`X_PRINTSERVER_PORT`
|用以提供打印服务的 port。

|`X_VFBSERVER_PORT`
|用以提供在虚拟帧缓存服务(virtual framebuffer server) 的 port。

|`X_NESTSERVER_PORT`
|用以提供嵌套 X 服务的 port。

|`X_FONTS_ENCODINGS_PORT`
|用以为字体提供编码的 port。

|`X_FONTS_MISC_PORT`
|用以提供多种位图字体的 port。

|`X_FONTS_100DPI_PORT`
|用以提供 100dpi 位图字体的 port。

|`X_FONTS_75DPI_PORT`
|用以提供 75dpi 位图字体的 port。

|`X_FONTS_CYRILLIC_PORT`
|用以提供西里尔位图字体的 port。

|`X_FONTS_TTF_PORT`
|用以提供 TrueType(R) 字体的 port。

|`X_FONTS_TYPE1_PORT`
|用以提供 Type1 字体的 port。

|`X_MANUALS_PORT`
|用以提供面向开发人员的联机手册的 port。
|===

[[using-x11-vars]]
.在变量中使用与 X11 有关的变量
[example]
====
[.programlisting]
....
# 使用某些 X11 库并依赖字体服务和西里尔字体。
RUN_DEPENDS=   ${LOCALBASE}/bin/xfs:${X_FONTSERVER_PORT} \
               ${LOCALASE}/lib/X11/fonts/cyrillic/crox1c.pcf.gz:${X_FONTS_CYRILLIC_PORT}

USE_XORG=      x11 xpm
....

====

[[x11-motif]]
=== 需要使用 Motif 的 port

如果您的 port 需要 Motif 库， 则应在 [.filename]#Makefile# 中定义 `USE_MOTIF`。 默认的 Motif 实现是 package:x11-toolkits/open-motif[]。 用户可以通过设置 `WANT_LESSTIF` 变量来选择 package:x11-toolkits/lesstif[] 代替它。

[.filename]#bsd.port.mk# 会将 `MOTIFLIB` 变量设置为到合适的 Motif 库的引用。 请使用补丁将您 port 中 [.filename]#Makefile# 或 [.filename]#Imakefile# 提到 Motif 库的地方改为 `${MOTIFLIB}`。

有两种比较常见的情况：

* 如果 port 中将 Motif 在其 [.filename]#Makefile# 或 [.filename]#Imakefile# 表达为 `-lXm`， 则简单地将其替换为 `${MOTIFLIB}`。
* 如果 port 在其 [.filename]#Imakefile# 中使用 `XmClientLibs`， 则将其改为 `${MOTIFLIB} ${XTOOLLIB} ${XLIB}`.

注意 `MOTIFLIB` (通常) 会展开为 `-L/usr/X11R6/lib -lXm` 或 `/usr/X11R6/lib/libXm.a`， 所以不需要在其前加入 `-L` 或 `-l`。

=== X11 字体

如果 port 将为 X Window 系统安装字体， 将这些字体放到 [.filename]#LOCALBASE/lib/X11/fonts/local#。

=== 通过 Xvfb 来获得虚拟的 `DISPLAY`

某些应用程序必须在有可用的 X11 显示的时候才能成功编译。 当编译的机器没有控制台时， 这会带来问题。 为了解决这个问题， 如果定义了适当的变量， 联编基础设施会启动采用虚拟帧缓存的 X server。 此时， 编译过程中将会传出可用的 `DISPLAY`。

[.programlisting]
....
USE_DISPLAY=  yes
....

[[desktop-entries]]
=== 桌面项

通过利用 `DESKTOP_ENTRIES` 变量， 可以很容易地在您的 port 中创建桌面项 (http://standards.freedesktop.org/desktop-entry-spec/latest/[Freedesktop 标准])。 这些项会在类似 GNOME 或 KDE 这样的符合这一标准的桌面环境中显示在应用程序菜单中。 这样做会自动创建、 安装 [.filename]#.desktop# 文件， 并将其加入 [.filename]#pkg-plist#。 其语法为：

[.programlisting]
....
DESKTOP_ENTRIES=  "NAME" "COMMENT" "ICON" "COMMAND" "CATEGORY" StartupNotify
....

您可以在 http://standards.freedesktop.org/menu-spec/latest/apa.html[ Freedesktop 网站上] 找到可用的分类名称。 `StartupNotify` 表示应用程序在支持启动通知的环境中清除状态信息。

例子：

[.programlisting]
....
DESKTOP_ENTRIES=  "ToME" "Roguelike game based on JRR Tolkien's work" \
                  "${DATADIR}/xtra/graf/tome-128.png" \
                  "tome -v -g" "Application;Game;RolePlaying;" \
                  false
....

[[using-gnome]]
== 使用 GNOME

FreeBSD/GNOME 项目组使用一组自己的变量来定义 port 所使用的 GNOME 组件。 http://www.FreeBSD.org/gnome/docs/porting/[这些变量的详细列表] 可以在 FreeBSD/GNOME 项目的主页找到。

[[using-qt]]
== 使用 Qt

[[qt-common]]
=== 在 port 中使用 Qt

.用于使用 Qt 的 port 的变量
[cols="1,1", frame="none"]
|===
|`USE_QT_VER`
|表示 port 用到了 Qt 工具套件。 可用的值包括 `3` 和 `4`； 用于指定使用的 Qt 的主版本。 此外， 系统会自动为 `configure` 脚本和 `make` 命令提供必要的参数。

|`QT_PREFIX`
|这个变量会自动设为 Qt 的安装路径 (只读变量)。

|`MOC`
|这个变量会自动设为 `moc` 的路径 (只读变量)。 默认值与 `USE_QT_VER` 变量的值有关。

|`QTCPPFLAGS`
|通过 `CONFIGURE_ENV` 传给 Qt 工具套件的编译参数。 默认配置与 `USE_QT_VER` 有关。

|`QTCFGLIBS`
|通过 `CONFIGURE_ENV` 传给 Qt 工具套件的连接库。 默认配置与 `USE_QT_VER` 有关。

|`QTNONSTANDARD`
|禁止系统自动修改 `CONFIGURE_ENV`、 `CONFIGURE_ARGS` 和 `MAKE_ENV`。
|===

.其他用于使用 Qt 4.x 的变量
[cols="1,1", frame="none"]
|===
|`QT_COMPONENTS`
|用于指定 Qt4 工具和函数库的依赖。 详情见后。

|`UIC`
|这个变量会自动设为 `uic` 的路径 (只读变量)。 默认值与 `USE_QT_VER` 有关。

|`QMAKE`
|这个变量会自动设为 `qmake` 的路径 (只读变量)。 其默认值与 `USE_QT_VER` 有关。

|`QMAKESPEC`
|这个变量会自动设为 `qmake` 配置文件的路径 (只读变量)。 其默认值与 `USE_QT_VER` 有关。
|===

当设置了 `USE_QT_VER` 时， 系统自动会给 `configure` 脚本传一系列有用的参数：

[.programlisting]
....
CONFIGURE_ARGS+= --with-qt-includes=${QT_PREFIX}/include \
                 --with-qt-libraries=${QT_PREFIX}/lib \
                 --with-extra-libs=${LOCALBASE}/lib \
                 --with-extra-includes=${LOCALBASE}/include
CONFIGURE_ENV+=  MOC="${MOC}" CPPFLAGS="${CPPFLAGS} ${QTCPPFLAGS}" LIBS="${QTCFGLIBS}" \
                 QTDIR="${QT_PREFIX}" KDEDIR="${KDE_PREFIX}"
....

如果将 `USE_QT_VER` 设为 `4`， 则还会进行下列配置：

[.programlisting]
....
CONFIGURE_ENV+= UIC="${UIC}" QMAKE="${QMAKE}" QMAKESPEC="${QMAKESPEC}"
MAKE_ENV+=      QMAKESPEC="${QMAKESPEC}"
....

[[qt4-components]]
=== 组件的选择 (仅限 Qt 4.x)

当把 `USE_QT_VER` 设为 4 时， 就可以通过 `QT_COMPONENTS` 变量来指定对 Qt4 工具和函数库的依赖了。 通过在组件的名称后面添加 `_build` 或 `_run` 这样的后缀， 则可相应地将这依赖关系限于联编或运行时刻。 在没有指定后缀时， 系统默认在联编和运行时刻均依赖该组件。 通常情况下在指明函数库一类的组件时应不使用后缀， 联编工具类组件应使用 `_build` 后缀， 而插件类组件， 则应使用 `_run` 后缀。 下表中列出了一些最常用的组件 (全部可用的组件， 则在 [.filename]#/usr/ports/Mk/bsd.qt.mk# 中的 `_QT_COMPONENTS_ALL` 列出)：

.可用的 Qt4 函数库组件
[cols="1,1", frame="none", options="header"]
|===
| 名字
| 描述

|`corelib`
|核心库 (在 port 只使用 `corelib` 而没有用到其他库时可以省略)

|`gui`
|图形用户界面库

|`network`
|网络函数库

|`opengl`
|OpenGL 函数库

|`qt3support`
|Qt3 兼容支持函数库

|`qtestlib`
|单元测试函数库

|`script`
|脚本函数库

|`sql`
|SQL 函数库

|`xml`
|XML 函数库
|===

您可以通过在成功编译之后， 通过在主可执行文件上运行 `ldd` 来确定所需的库。

.可用的 Qt4 工具组件
[cols="1,1", frame="none", options="header"]
|===
| 名字
| 描述

|`moc`
|元对象编译器 (几乎所有的 Qt 应用程序在联编过程中都需要它)

|`qmake`
|Makefile 生成器 / 联编工具

|`rcc`
|资源编译器 (如果应用程序中包含 [.filename]#*.rc# 或 [.filename]#*.qrc# 文件， 就需要它)

|`uic`
|用户界面编译器 (如果应用程序中包含使用 Qt Designer 创建的 [.filename]#*.ui# 文件时就需要它 - 一般说来 Qt 应用程序都会使用 GUI 的)
|===

.可用的 Qt4 插件组件
[cols="1,1", frame="none", options="header"]
|===
| 名字
| 描述

|`iconengines`
|SVG 图标引擎插件 (如果应用程序使用 SVG 图标)

|`imageformats`
|用于 GIF、 JPEG、 MNG 和 SVG 的 imageformat 插件 (如果应用程序使用图片文件)
|===

[[qt4-components-example]]
.选择 Qt4 组件
[example]
====
在这个例子中， 我们将要移植的应用程序用到了 Qt4 图形用户界面函数库、 Qt4 核心 (core) 函数库、 所有 Qt4 代码生成工具以及 Qt4 的 Makefile 生成器。 由于 gui 函数库会自动附带对核心函数库的依赖， 因此并不需要明确指出需要 corelib 的依赖关系。 Qt4 代码生成工具 moc、 uic 和 rcc 以及 Makefile 生成器 qmake 只在联编过程中才会用到， 因此可以指定 `_build` 后缀：

[.programlisting]
....
USE_QT_VER=    4
QT_COMPONENTS= gui moc_build qmake_build rcc_build uic_build
....

====

[[qt-additional]]
=== 其他考虑

如果应用程序没有提供 [.filename]#configure# 文件， 而是给了一个 [.filename]#.pro# 文件， 则应这样：

[.programlisting]
....
HAS_CONFIGURE=	yes

do-configure:
        @cd ${WRKSRC} && ${SETENV} ${CONFIGURE_ENV} \
                ${QMAKE} -unix PREFIX=${PREFIX} texmaker.pro
....

请注意， 这与系统提供的 [.filename]#BUILD.sh# 中的 `qmake` 类似。 传递 `CONFIGURE_ENV` 能够确保 `qmake` 可以看到 `QMAKESPEC` 变量， 否则它可能无法正常工作。 `qmake` 会生成标准的 Makefile， 因此无需自行编写 `build` target。

Qt 应用程序通常会编写为能够跨平台使用， 通常 X11/Unix 并不是开发它的平台， 有时这会导致一些边边角角的问题， 例如：

* _缺少必要的 includepaths。_ 许多应用程序会使用托盘图标支持， 但忽略了这些头或库文件需要在 X11 目录中查找。 您可以通过命令行告诉 `qmake` 将这些头文件和函数库加入到搜索路径中， 例如：
+
[.programlisting]
....
${QMAKE} -unix PREFIX=${PREFIX} INCLUDEPATH+=${LOCALBASE}/include \
	LIBS+=-L${LOCALBASE}/lib sillyapp.pro
....

* _有问题的安装路径。_ 有时， 类似图标或 .desktop 文件这样的一些数据， 默认情况下没有安装到 XDG-兼容的程序会扫描的路径中。 package:editors/texmaker[] 就是一个这样的例子 - 请参考这个 port 的 [.filename]#files# 目录中的 [.filename]#patch-texmaker.pro#， 以了解如何在 Qmake 工程文件中修正这个问题。

[[using-kde]]
== 使用 KDE

[[kde-variables]]
=== 变量定义 (只用于 KDE 3.x)

.用于使用 KDE 3.x 的 port 的变量
[cols="1,1", frame="none"]
|===
|`USE_KDELIBS_VER`
|表示 port 用到了 KDE 库。 这个变量可以指定希望使用的 KDE 主版本号， 如果设置了这个变量， 则系统也会将 `USE_QT_VER` 设为适当的版本。 该变量目前唯一有效的值是 `3`。

|`USE_KDEBASE_VER`
|表示 port 用到了 KDE 的基本系统。 这个变量可以指定希望使用的 KDE 主版本号， 如果设置了这个变量， 则系统也会将 `USE_QT_VER` 设为适当的版本。 该变量目前唯一有效的值是 `3`。
|===

[[kde4-variables]]
=== 用于 KDE 4 的变量定义

如果您的应用程序需要使用 KDE 4.x， 则应将 `USE_KDE4` 设为所需组件的列表。 下面列出一些最常用到的组件 (最新的组件列表位于 [.filename]#/usr/ports/Mk/bsd.kde4.mk# 中的 `_USE_KDE4_ALL`)：

.可用的 KDE4 组件
[cols="1,1", frame="none", options="header"]
|===
| 名称
| 说明

|`akonadi`
|个人信息管理 (PIM)存储服务

|`automoc4`
|令 port 使用 automoc4 联编工具集

|`kdebase`
|基本的 KDE 应用程序 (Konqueror、 Dolphin、 Konsole)

|`kdeexp`
|试验性的 KDE 库 (包含尚未完全确定不变的 API)

|`kdehier`
|常用的 KDE 目录层次结构

|`kdelibs`
|基本 KDE 库

|`kdeprefix`
|如果设置了这个选项， 则 port 将安装到 `${KDE4_PREFIX}` 而不是 `${LOCALBASE}`

|`pimlibs`
|PIM 函数库

|`workspace`
|用于组成桌面的应用程序和函数库 (Plasma、 KWin)
|===

KDE 4.x port 会安装到 `${KDE4_PREFIX}`， 目前是 [.filename]#/usr/local/kde4#， 以避免与 KDE 3.x ports 冲突。 这是通过指定 `kdeprefix` 组件来实现的， 它表示替换默认的 `PREFIX`。 不过， port 仍会遵循通过 `MAKEFLAGS` 环境变量设置的 `PREFIX` 以及其它 make 参数。

KDE 4.x ports 有可能和 KDE 3.x ports 冲突， 因此如果启用了 `kdeprefix` 组件， 它们会安装到 `${KDE4_PREFIX}`。 目前 `KDE4_PREFIX` 的默认值是 [.filename]#/usr/local/kde4#。 也可以将 KDE 4.x ports 安装到自定义的 `PREFIX`。 当 `PREFIX` 是通过 `MAKEFLAGS` 环境变量， 或直接在 make 命令行指定时， 它会替换 `kdeprefix` 提供的配置。

[[kde4-components-example]]
.`USE_KDE4` 示例
[example]
====
下面是一个简单的 KDE 4 port。 `USE_CMAKE` 指定 port 使用 CMake - 许多 KDE 4 项目所使用的配置工具。 `USE_KDE4` 则引入 KDE 函数库， 并令 port 在联编阶段使用 automoc4。 需要的 KDE 组件， 以及其他依赖的组件可以从 configure 的日志中获知。 `USE_KDE4` 并不会自动设置 `USE_QT_VER`。 如果 port 需要使用某些 Qt4 组件， 则需要设置 `USE_QT_VER` 并指定所需要的组件。 

[.programlisting]
....
USE_CMAKE=     yes
USE_KDE4=      automoc4 kdelibs kdeprefix
USE_QT_VER=    4
QT_COMPONENTS= qmake_build moc_build rcc_build uic_build
....

====

[[using-java]]
== 使用 Java

[[java-variables]]
=== 变量定义

如果您的 port 需要 Java(TM) 开发包 (JDK(TM)) 来完成联编、 支持运行， 甚至完成解开源代码包这样的工作， 就应该定义 `USE_JAVA`。

在 Ports Collection 中有许多不同的 JDK， 它们的版本各不相同， 或是来自不同的供应商。 如果您的 port 必须使用其中的某个特定的版本， 也可以予以定义。 最新的稳定版本是 package:java/jdk16[]。

.用到 Java 的 port 可以使用的变量
[cols="1,1", frame="none", options="header"]
|===
| 变量
| 意义

|`USE_JAVA`
|只有定义它才能使其它变量生效。

|`JAVA_VERSION`
|用空格分开的适合 port 使用的 Java 版本。 可选的 `"+"` 可以用于指定某个范围的版本 (可以用： `1.5[+] 1.6[+] 1.7[+]`)。

|`JAVA_OS`
|用空格分开的适应 port 的 JDK port 操作系统类型 (可以用： `native linux`)。

|`JAVA_VENDOR`
|用空格分开的适应 port 的 JDK port 供应商 (可以用： `freebsd bsdjava sun openjdk`)。

|`JAVA_BUILD`
|设置这个变量表示所选的 JDK port 应被列入 port 的联编依赖关系。

|`JAVA_RUN`
|设置这个变量表示所选的 JDK port 应被列入 port 的运行环境依赖关系。

|`JAVA_EXTRACT`
|设置这个变量表示所选的 JDK port 应被列入 port 的解压缩支持依赖关系。
|===

下面是在设置了 `USE_JAVA` 之后， port 能够从系统中获得的配置：

.向使用了 Java 的 port 提供的变量
[cols="1,1", frame="none", options="header"]
|===
| 变量
| 值

|`JAVA_PORT`
|JDK port 的名字 (例如 `'java/diablo-jdk16'`)。

|`JAVA_PORT_VERSION`
|JDK port 的完整版本 (例如 `'1.6.0'`)。 如果您只需要版本号的前两位， 则可用 `${JAVA_PORT_VERSION:C/^([0-9])\.([0-9])(.*)$/\1.\2/}`。

|`JAVA_PORT_OS`
|所用 JDK port 的操作系统 (例如 `'native'`)。

|`JAVA_PORT_VENDOR`
|所用 JDK port 的供应商 (例如 `'freebsd'`)。

|`JAVA_PORT_OS_DESCRIPTION`
|所用 JDK port 操作系统的描述 (例如 `'Native'`)。

|`JAVA_PORT_VENDOR_DESCRIPTION`
|所用 JDK port 供应商的描述 (例如 `'FreeBSD Foundation'`)。

|`JAVA_HOME`
|JDK 的安装目录 (例如 [.filename]#'/usr/local/diablo-jdk1.6.0'#)。

|`JAVAC`
|所用 Java 编译器的完整路径 (例如 [.filename]#'/usr/local/diablo-jdk1.6.0/bin/javac'#)。 

|`JAR`
|所用 `jar` 工具的完整路径 (例如 [.filename]#'/usr/local/diablo-jdk1.6.0/bin/jar'# 或 [.filename]#'/usr/local/bin/fastjar'#)。

|`APPLETVIEWER`
|所用 `appletviewer` 工具的完整路径 (例如 [.filename]#'/usr/local/diablo-jdk1.6.0/bin/appletviewer'#)。

|`JAVA`
|所用 `java` 执行文件的完整路径。 您应使用它来执行 Java 程序 (例如 [.filename]#'/usr/local/diablo-jdk1.6.0/bin/java'#)。

|`JAVADOC`
|所用 `javadoc` 工具的完整路径。

|`JAVAH`
|所用 `javah` 程序的完整路径。

|`JAVAP`
|所用 `javap` 程序的完整路径。

|`JAVA_KEYTOOL`
|所用 `keytool` 工具的完整路径。

|`JAVA_N2A`
|所用 `native2ascii` 工具的完整路径。

|`JAVA_POLICYTOOL`
|所用 `policytool` 程序的完整路径。

|`JAVA_SERIALVER`
|所用 `serialver` 程序的完整路径。

|`RMIC`
|所用 RMI 桩/架 生成器， `rmic` 的完整路径。

|`RMIREGISTRY`
|所用 RMI 注册表程序， `rmiregistry` 的完整路径。

|`RMID`
|所用 RMI 服务程序 `rmid` 的完整路径。

|`JAVA_CLASSES`
|所用 JDK 类文件目录的完整路径。 [.filename]#${JAVA_HOME}/jre/lib/rt.jar#。
|===

您可以使用 `java-debug` make target 以获取用于调试 port 的信息。 大多数前述变量的值皆会予以呈现。

此外， 还会定义下述常量， 以确保所有的 Java port 均以一致之方式安装：

.为使用 Java 的 port 定义的常量
[cols="1,1", frame="none", options="header"]
|===
| 常量
| 值

|`JAVASHAREDIR`
|所有 Java 相关资料的安装根目录。 默认值： [.filename]#${PREFIX}/shared/java#. 

|`JAVAJARDIR`
|用以安装 JAR 文件的目录。 默认值： [.filename]#${JAVASHAREDIR}/classes#。

|`JAVALIBDIR`
|其它 port 安装的 JAR 文件所在的目录。 默认值： [.filename]#${LOCALBASE}/shared/java/classes#。
|===

相关的项也会定义在 `PLIST_SUB` (在 crossref:plist[plist-sub, 根据 `make` 变量对 pkg-plist 进行修改] 中进行介绍) 和 `SUB_LIST` 中。

[[java-building-with-ant]]
=== 采用 Ant 进行联编

如果 port 采用 Apache Ant 进行联编， 则需要定义 `USE_ANT`。 如是， 则 Ant 将作为 子-make 命令来使用。 如果 port 未定义 `do-build` target， 则将默认依 `MAKE_ENV`、 `MAKE_ARGS` 和 `ALL_TARGET`。 的设置执行 Ant。 这类似于 <<building>> 中介绍的关于 `USE_GMAKE` 的机制。

[[java-best-practices]]
=== 最佳实践

如果您正移植某个 Java 库， 您的 port 应把 JAR 文件安装到 [.filename]#${JAVAJARDIR}#， 而其它文件则应放在 [.filename]#${JAVASHAREDIR}/${PORTNAME}# 下 (除了文档， 参见下文)。 要减少打包文件的尺寸， 您可以直接在 [.filename]#Makefile# 中引用这些 JAR 文件， 具体做法是使用下面的语句 (此处的 [.filename]#myport.jar# 是作为 port 一部分安装的 JAR 文件的名字)：

[.programlisting]
....
PLIST_FILES+= %%JAVAJARDIR%%/myport.jar
....

移植 Java 应用程序时， port 通常会希望将所有文件安装到同一目录 (包括其依赖的 JAR)。 这时强烈建议使用 [.filename]#${JAVASHAREDIR}/${PORTNAME}#。 移植软件的开发人员， 可以自行决定是否将所依赖的其它 JAR 安装到此目录， 或直接使用已经装好的那些 (来自 [.filename]#${JAVAJARDIR}#)。

无论您正制作哪一类的 port (库或者应用程序)， 附加的文档都应安装到和其它 port <<install-documentation,同样的位置>>。 已经知道， JavaDoc 会根据 JDK 版本的不同而产生不同的文件。 对于那些不打算强制使用某一特定版本 JDK 的 port 而言， 这无疑提高了制作装箱单 ([.filename]#pkg-plist#) 的难度。 这是为什么强烈建议使用 `PORTDOCS` 宏的原因。 更进一步， 即使您能够预测 `javadoc` 将要生成的文件， 所需的 [.filename]#pkg-plist# 的尺寸， 也是鼓吹使用 `PORTDOCS` 的一大理由。

`DATADIR` 的默认值是 [.filename]#${PREFIX}/shared/${PORTNAME}#。 对 Java port 而言将 `DATADIR` 改为 [.filename]#${JAVASHAREDIR}/${PORTNAME}# 是一个好主意。 当然， `DATADIR` 会自动加到 `PLIST_SUB` 中 (在 crossref:plist[plist-sub, 根据 `make` 变量对 pkg-plist 进行修改] 有所介绍) 因此您可以在 [.filename]#pkg-plist# 中直接使用 `%%DATADIR%%`。

撰写本文时， 对是应该从源代码联编， 还是直接安装预编译的 Java ports 安装包并没有明确的规定。 尽管如此， http://www.freebsd.org/java/[FreeBSD Java Project] 的开发人员仍鼓励移植软件的开发者在不麻烦的情况下尽可能从源代码完成联编。

本节中所介绍的全部特性， 均是在 [.filename]#bsd.java.mk# 中实现的。 如果您感觉自己的 port 需要更为复杂的 Java 支持， 请首先参阅 http://www.freebsd.org/cgi/cvsweb.cgi/ports/Mk/bsd.java.mk[ bsd.java.mk CVS 日志]， 因为通常撰文介绍最新特性需要一些时间。 此外， 如果您认为所缺少的支持对许多其它 Java port 亦属有益， 请在 freebsd-java 对其进行讨论。

在 PR 中的 `java` 类别， 主要是用于 FreeBSD Java project 移植 JDK 本身之用。 因而， 提交您的 Java port 时， 应归入 `ports` 类别， 除非您正尝试解决的问题是 JDK 实现本身或 [.filename]#bsd.java.mk# 的。

类似地， 您应参考 crossref:makefile[makefile-categories, 分类] 中所详述的关于 `CATEGORIES` 在 Java port 中的使用规则。

[[using-php]]
== Web 应用， Apache 和 PHP

[[using-apache]]
=== Apache

.用到 Apache 的 port 可以使用的变量
[cols="1,1", frame="none"]
|===
|`USE_APACHE`
|此 port 需要 Apache。 可用的值： `yes` (任意可用版本)、 `1.3`、 `2.0`、 `2.2`、 `2.0+`、 等等。 默认依赖的版本是 `1.3`。

|`WITH_APACHE2`
|此 port 需要 Apache 2.0。 如果没有这个变量， 则 port 将依赖 Apache 1.3。 这一变量目前已经过时， 因而不应继续使用。

|`APXS`
|到 `apxs` 可执行文件的完整路径。 您可以在 port 中替代该值。

|`HTTPD`
|到 `httpd` 可执行文件的完整路径。 您可以在 port 中替代该值。

|`APACHE_VERSION`
|目前系统中安装的 Apache 版本 (只读变量)。 这一变量只有在引用了 [.filename]#bsd.port.pre.mk# 之后才能使用， 其可能的值为： `13`、 `20`、 `22`。

|`APACHEMODDIR`
|Apache 模块所在的文件夹。 在 pkg-plist 中， 这一变量会自动展开。

|`APACHEINCLUDEDIR`
|Apache 头文件所在的文件夹。 在 pkg-plist 中， 这一变量会自动展开。

|`APACHEETCDIR`
|Apache 配置文件所在的文件夹。 在 pkg-plist 中， 这一变量会自动展开。
|===

.在移植 Apache 模块时比较有用的变量
[cols="1,1", frame="none"]
|===
|`MODULENAME`
|模块的名称。 默认值为 `PORTNAME`。 例如： `mod_hello`

|`SHORTMODNAME`
|模块的简略名字。 默认情况下会自动根据 `MODULENAME` 计算， 但您也可以自行设置值来替代它。 例如： `hello`

|`AP_FAST_BUILD`
|使用 `apxs` 来编译和安装模块。

|`AP_GENPLIST`
|同时自动创建 [.filename]#pkg-plist#。

|`AP_INC`
|在编译过程中， 将指定的目录加入到搜索头文件的目录中。

|`AP_LIB`
|在编译过程中， 将指定的目录加入到搜索函数库的目录中。

|`AP_EXTRAS`
|传递给 `apxs` 的额外参数。
|===

[[web-apps]]
=== Web 应用

Web 应用程序应安装到 [.filename]#PREFIX/www/应用程序的名字#。 为方便起见， 这个路径在 [.filename]#Makefile# 和 [.filename]#pkg-plist# 均以 `WWWDIR` 变量的形式提供。 在 [.filename]#Makefile# 中可以使用 `WWWDIR_REL` 来表示包含了 `PREFIX` 的该变量值。

web 服务器进程所用的用户和用户组， 分别以 `WWWOWN` 和 `WWWGRP` 变量的形式提供， 如果您需要修改某些文件的属主的话。 这两个变量的默认值均为 `www`。 如果您的 port 希望使用其他值， 请使用 `WWWOWN?= myuser` 这种写法， 以便让用户能够更容易地修改它。

除非您的 port 必需使用 Apache， 否则不要将其写入依赖关系。 请尊重运行您的应用程序的用户选择 Apache 以外的其他 web 服务器的需求。

[[php-variables]]
=== PHP

.用到 PHP 的 port 中可以使用的变量
[cols="1,1", frame="none"]
|===
|`USE_PHP`
|此 port 需要 PHP。 取值为 `yes` 将把 PHP 加入依赖关系。 此外， 还可以在此指定将所需要的 PHP 扩展模块。 例如： `pcre xml gettext`

|`DEFAULT_PHP_VER`
|选择在没有安装 PHP 时自动安装的 PHP 主版本。 默认是 `4`。 可选 `4`、 `5` 之一。

|`IGNORE_WITH_PHP`
|此 port 无法与给定版本的 PHP 一同工作。 可选值为 `4`、 `5` 之一。

|`USE_PHPIZE`
|此 port 将作为 PHP 扩展模块进行联编。

|`USE_PHPEXT`
|此 port 将作为 PHP 扩展， 且需要作为扩展模块注册。

|`USE_PHP_BUILD`
|联编依赖于 PHP。

|`WANT_PHP_CLI`
|希望使用 CLI (命令行) 版本的 PHP。

|`WANT_PHP_CGI`
|希望使用 CGI 版本的 PHP。

|`WANT_PHP_MOD`
|希望使用 Apache 模块版本的 PHP。

|`WANT_PHP_SCR`
|希望使用 CLI 或 CGI 版本的 PHP。

|`WANT_PHP_WEB`
|希望使用 Apache 模块或 CGI 版本的 PHP。
|===

=== PEAR 模块

移植 PEAR 模块的过程非常简单。

使用 `FILES`、 `TESTS`、 `DATA`、 `SQLS`、 `SCRIPTFILES`、 `DOCS` 以及 `EXAMPLES` 这些变量来指明您希望安装的文件。 所有这里列出的文件都会自动安装到合适的位置， 并加入 [.filename]#pkg-plist#。

在 [.filename]#Makefile# 文件的最后一行引入 [.filename]#${PORTSDIR}/devel/pear/bsd.pear.mk#。

[[pear-makefile]]
.用于 PEAR 类的 Makefile 例子
[example]
====
[.programlisting]
....
PORTNAME=       Date
PORTVERSION=    1.4.3
CATEGORIES=     devel www pear

MAINTAINER=     example@domain.com
COMMENT=        PEAR Date and Time Zone Classes

BUILD_DEPENDS=  ${PEARDIR}/PEAR.php:${PORTSDIR}/devel/pear-PEAR
RUN_DEPENDS=    ${BUILD_DEPENDS}

FILES=          Date.php Date/Calc.php Date/Human.php Date/Span.php     \
                Date/TimeZone.php
TESTS=          test_calc.php test_date_methods_span.php testunit.php   \
                testunit_date.php testunit_date_span.php wknotest.txt   \
                bug674.php bug727_1.php bug727_2.php bug727_3.php       \
                bug727_4.php bug967.php weeksinmonth_4_monday.txt       \
                weeksinmonth_4_sunday.txt weeksinmonth_rdm_monday.txt   \
                weeksinmonth_rdm_sunday.txt
DOCS=           TODO
_DOCSDIR=       .

.include <bsd.port.pre.mk>
.include "${PORTSDIR}/devel/pear/bsd.pear.mk"
.include <bsd.port.post.mk>
....

====

[[using-python]]
== 使用 Python

Ports 套件支持同时并行安装多个不同的 Python 版本。 Ports 应确保能够根据用户配置的 `PYTHON_VERSION` 变量使用正确的 `python` 解释器。 一般说来， 这是通过将脚本中的 `python` 路径名替换为 `PYTHON_CMD` 变量的值来实现的。

在 `PYTHON_SITELIBDIR` 下安装文件的 ports 应在包名上使用 `pyXY-` 前缀， 以便明示它们将会配合哪个 Python 版本使用。

[.programlisting]
....
PKGNAMEPREFIX= ${PYTHON_PKGNAMEPREFIX}
....

.对用到 Python 的 port 最有用的一些变量
[cols="1,1", frame="none"]
|===
|`USE_PYTHON`
|此 port 需要 Python。 可以用 `2.3+` 这样的形式来指定所希望的版本。 除此之外， 也可以用横线来分隔两个版本号， 以表示某个范围的版本， 例如： `2.1-2.3`

|`USE_PYDISTUTILS`
|使用 Python distutils 来完成配置、 编译和安装。 对包含 [.filename]#setup.py# 的 port 而言这是必需的。 它会自动覆盖默认的 `do-build` 以及 `do-install` 这两个 target。 如未定义 `GNU_CONFIGURE`， 它还会改变 `do-configure`。

|`PYTHON_PKGNAMEPREFIX`
|作为 `PKGNAMEPREFIX` 来区分不同 Python 版本的 package。 例如： `py24-`

|`PYTHON_SITELIBDIR`
|全站 package 所在的目录， 它包括了 Python 的安装目录 (通常是 `LOCALBASE`)。 在安装 Python 模块时， `PYTHON_SITELIBDIR` 变量会非常有用。

|`PYTHONPREFIX_SITELIBDIR`
|去掉了 PREFIX 部分的 PYTHON_SITELIBDIR。 应尽可能在 [.filename]#pkg-plist# 中使用 `%%PYTHON_SITELIBDIR%%`。 `%%PYTHON_SITELIBDIR%%` 的默认值是 `lib/python%%PYTHON_VERSION%%/site-packages`

|`PYTHON_CMD`
|Python 解释器的命令行， 包括版本号。

|`PYNUMERIC`
|将数值处理扩展模块加入依赖关系。

|`PYNUMPY`
|对新增的数值计算扩展, numpy的依赖。 (PYNUMERIC 目前已被作者淘汰)。

|`PYXML`
|将 XML 扩展模块加入依赖关系。 (对于 Python 2.0 和更高版本不再需要， 因为它已经成为了标准组件)。

|`USE_TWISTED`
|将 twistedCore 加入依赖关系。 也可以用这个变量指定所需的组件， 例如： `web lore pair flow`

|`USE_ZOPE`
|加入对 Zope， 一种 web 应用平台的依赖。 这会把 Python 依赖改为 Python 2.3。 此外 `ZOPEBASEDIR` 也会自动设为 Zope 安装目录的位置。
|===

完整的可用变量列表， 可以在 [.filename]#/usr/ports/Mk/bsd.python.mk# 中找到。

[[using-tcl]]
== 使用 Tcl/Tk

Ports 套件支持同时安装多个 Tcl/Tk 版本。 Ports 应至少支持默认的 Tcl/Tk 版本， 以及通过 `USE_TCL` 和 `USE_TK` 变量指定的更高版本。 希望使用的 `tcl` 版本， 则可以通过 `WITH_TCL_VER` 变量来使用。

.用到 Tcl/Tk 的 port 可以使用的变量
[cols="1,1", frame="none"]
|===
|`USE_TCL`
|表示 port 依赖于 Tcl 函数库 (不是 shell)。 可以指定需要的最低版本， 例如 84+。 不支持的版本， 可以在 `INVALID_TCL_VER` 变量中逐个指定。

|`USE_TCL_BUILD`
|表示 port 在联编过程中需要使用 Tcl。

|`USE_TCL_WRAPPER`
|需要使用 Tcl shell 而不需要特定版本的 `tclsh` 的 port 可以使用这个新变量。 系统中会安装 `tclsh` wrapper， 用户则可以指定所希望的 `tcl` shell。

|`WITH_TCL_VER`
|由用户定义的、 希望使用的 Tcl 版本。

|`UNIQUENAME_WITH_TCL_VER`
|和 `WITH_TCL_VER` 类似， 但是针对 port 指定的。

|`USE_TCL_THREADS`
|需要包含线程支持的 Tcl/Tk。

|`USE_TK`
|表示 port 依赖于 Tk 库 (不是 wish shell)。 它同时会隐含将 `USE_TCL` 设置为相同的值。 更多的描述， 请参考 `USE_TCL` 变量。

|`USE_TK_BUILD`
|与 `USE_TCL_BUILD` 变量表达类似的含义。

|`USE_TK_WRAPPER`
|与 `USE_TCL_WRAPPER` 变量表达类似的含义。

|`WITH_TK_VER`
|表达与 `WITH_TCL_VER` 变量类似的含义， 它同时会隐含将 `WITH_TCL_VER` 设置为相同的值。
|===

可用的变量的完整列表， 可以在 [.filename]#/usr/ports/Mk/bsd.tcl.mk# 中找到。

[[using-emacs]]
== 使用 Emacs

本节尚有待撰写。

[[using-ruby]]
== 使用 Ruby

.使用 Ruby 的 port 可以使用的变量
[cols="1,1", frame="none", options="header"]
|===
| 变量
| 说明

|`USE_RUBY`
|此 port 需要 Ruby。

|`USE_RUBY_EXTCONF`
|此 port 使用 [.filename]#extconf.rb# 来完成配置。

|`USE_RUBY_SETUP`
|此 port 使用 [.filename]#setup.rb# 来完成配置。

|`RUBY_SETUP`
|将此变量名设置为所用的 [.filename]#setup.rb# 的文件名。 通常会是 [.filename]#install.rb#。
|===

下表展示了 ports 系统提供给 port 作者的一些变量。 您应使用这些变量， 以便把文件装到合适的位置。 请尽可能多地在 [.filename]#pkg-plist# 中使用它们。 这些变量不应在 port 中重新定义。

.使用 Ruby 的 port 中的一些可用的只读变量
[cols="1,1,1", frame="none", options="header"]
|===
| 变量
| 说明
| 示范值

|`RUBY_PKGNAMEPREFIX`
|作为 `PKGNAMEPREFIX` 以区分用于不同 Ruby 版本的 package。
|`ruby18-`

|`RUBY_VERSION`
|`x.y.z` 形式的完整 ruby 版本。
|`1.8.2`

|`RUBY_SITELIBDIR`
|平台无关库的安装路径。
|`/usr/local/lib/ruby/site_ruby/1.8`

|`RUBY_SITEARCHLIBDIR`
|平台相关的库的安装路径。
|`/usr/local/lib/ruby/site_ruby/1.8/amd64-freebsd6`

|`RUBY_MODDOCDIR`
|模块文档的安装路径。
|`/usr/local/shared/doc/ruby18/patsy`

|`RUBY_MODEXAMPLESDIR`
|模块用例的安装路径。
|`/usr/local/shared/examples/ruby18/patsy`
|===

可用变量的完整列表， 可以在 [.filename]#/usr/ports/Mk/bsd.ruby.mk# 中找到。

[[using-sdl]]
== 使用 SDL

变量 `USE_SDL` 可以用于自动配置 port 的依赖关系， 以适应使用类似 package:devel/sdl12[] 和 package:x11-toolkits/sdl_gui[] 这些依赖 SDL 的库的情形。

目前系统能够识别下列 SDL 库：

* sdl: package:devel/sdl12[]
* gfx: package:graphics/sdl_gfx[]
* gui: package:x11-toolkits/sdl_gui[]
* image: package:graphics/sdl_image[]
* ldbad: package:devel/sdl_ldbad[]
* mixer: package:audio/sdl_mixer[]
* mm: package:devel/sdlmm[]
* net: package:net/sdl_net[]
* sound: package:audio/sdl_sound[]
* ttf: package:graphics/sdl_ttf[]

因此， 如果 port 需要依赖 package:net/sdl_net[] 和 package:audio/sdl_mixer[]， 则对应的写法将是：

[.programlisting]
....
USE_SDL=        net mixer
....

同时， package:net/sdl_net[] 和 package:audio/sdl_mixer[] 所依赖的 package:devel/sdl12[] 也会被自动地加入。

加入您使用 `USE_SDL`， 它将自动地：

* 将对于 sdl12-config 的依赖关系加入到 `BUILD_DEPENDS`
* 将变量 `SDL_CONFIG` 加入到 `CONFIGURE_ENV`
* 将对所选的库的依赖， 加入到 `LIB_DEPENDS`

要检查某个特定的 SDL 库是否可用， 可以通过 `WANT_SDL` 变量来达到目的：

[.programlisting]
....
WANT_SDL=yes

.include <bsd.port.pre.mk>

.if ${HAVE_SDL:Mmixer}!=""
USE_SDL+=   mixer
.endif

.include <bsd.port.post.mk>
....

[[using-wx]]
== 使用 wxWidgets

这一节介绍了在 ports tree 中的 wxWidgets 库的现状， 以及它与 ports 系统的集成。

[[wx-introduction]]
=== 介绍

许多不同版本的 wxWidgets 库之间是存在相互冲突的 (它们会安装同名的文件) 在 ports 系统中， 这一问题是通过将不同的版本以包含版本号后缀的名字安装来解决的。

这样做的一个最明显的缺点是， 应用程序必须进行修改， 才能找到所希望的版本。 幸运的是， 多数应用程序会调用 `wx-config` 脚本来确定需要的编译器和连接器选项。 这个脚本会随可用的版本不同而有不同的名字。 主要的应用程序都会尊重环境变量的配置， 或提供一个 configure 参数， 用以指定调用哪个 `wx-config`。 如果不是这样的话， 就需要对应用程序打补丁了。

[[wx-version]]
=== 版本的选择

为了让您的 port 使用指定版本的 wxWidgets， 可以定义两个变量 (如果只定义了一个， 则另一个会取默认值)：

[[wx-ver-sel-table]]
.用于选择 wxWidgets 版本的变量
[cols="1,1,1", frame="none", options="header"]
|===
| 变量
| 说明
| 默认值

|`USE_WX`
|列出这个 port 能使用的版本
|全部版本

|`USE_WX_NOT`
|列出这个 port 不能使用的版本
|无
|===

下面是可用的 wxWidgets 版本， 以及对应的 ports：

.可用的 wxWidgets versions
[cols="1,1", frame="none", options="header"]
|===
| 版本
| Port

|`2.4`
|package:x11-toolkits/wxgtk24[]

|`2.6`
|package:x11-toolkits/wxgtk26[]

|`2.8`
|package:x11-toolkits/wxgtk28[]
|===

[NOTE]
====
从 `2.5` 版开始， 也提供了对应的 Unicode 版本， 这种版本可以通过 slave port 安装， 与普通版本相比， 它会多一个 `-unicode` 后缀， 不过这可以通过使用变量来处理 (请参见 <<wx-unicode>>)。
====

在 <<wx-ver-sel-table>> 中的变量， 可以设为下列值或由空格分隔的组合：

.wxWidgets 版本
[cols="1,1", frame="none", options="header"]
|===
| 说明
| 例子

|单个版本
|`2.4`

|某版本以上版本
|`2.4+`

|某版本以下版本
|`2.6-`

|某段版本 (版本号较小的必须在前)
|`2.4-2.6`
|===

除此之外， 还有一些用以从可用的本那本中选择所希望的版本的变量。 这种变量也可以设为一组版本， 而靠前的版本的优先级更高。

.用于选择希望的版本的 wxWidgets versions
[cols="1,1", frame="none", options="header"]
|===
| 变量名
| 用于

|`WANT_WX_VER`
|port

|`WITH_WX_VER`
|用户
|===

[[wx-components]]
=== 选择组件

也有一些其他应用， 尽管它们本身并不是 wxWidgets 库， 但却与之相关。 这些应用程序可以在 `WX_COMPS` 变量中使用， 以下是可用的组件：

.可用的 wxWidgets 组件
[cols="1,1,1", frame="none", options="header"]
|===
| 名称
| 说明
| 版本限制

|`wx`
|主库
|无

|`contrib`
|第三方库
|`无`

|`python`
|wxPython (Python 绑定)
|`2.4-2.6`

|`mozilla`
|wxMozilla
|`2.4`

|`svg`
|wxSVG
|`2.6`
|===

您可以为每个依赖的组件， 通过冒号分隔的后缀指定其类型。 如果没有指定， 则会使用默认的依赖类型 (参见 <<wx-def-dep-types>>)。 下面是可用的类型：

.可用的 wxWidgets 依赖类型
[cols="1,1", frame="none", options="header"]
|===
| 名称
| 说明

|`build`
|联编时需要该组件， 相当于 `BUILD_DEPENDS`

|`run`
|运行时需要该组件， 相当于 `RUN_DEPENDS`

|`lib`
|联编和运行时均需要该组件， 相当于 `LIB_DEPENDS`
|===

组件的默认依赖关系类型， 如下表所示：

[[wx-def-dep-types]]
.默认的 wxWidgets 依赖关系类型
[cols="1,1", frame="none", options="header"]
|===
| 组件
| 依赖关系类型

|`wx`
|`lib`

|`contrib`
|`lib`

|`python`
|`run`

|`mozilla`
|`lib`

|`svg`
|`lib`
|===

[[wx-components-example]]
.选择 wxWidgets 组件
[example]
====
下面的片段展示了使用 wxWidgets 版本 `2.4` 及第三方库的方法。

[.programlisting]
....
USE_WX=       2.4
WX_COMPS=     wx contrib
....

====

[[wx-unicode]]
=== Unicode

wxWidgets 库从其 `2.5` 版开始支持 Unicode 了。 在 ports 系统中， 这两种版本均有提供， 并可以通过下列变量来选择：

[[wx-unicode-var-table]]
.用以在 Unicode 版本的 wxWidgets 的变量
[cols="1,1,1", frame="none", options="header"]
|===
| 变量
| 说明
| 作用

|`WX_UNICODE`
|该 port _只能_ 配合 Unicode 版本使用
|port

|`WANT_UNICODE`
|port 能够与两种版本配合使用， 但希望使用 Unicode 版本
|port

|`WITH_UNICODE`
|令 port 使用 Unicode 版本
|用户

|`WITHOUT_UNICODE`
|令 port 使用普通版本， 如果支持的话 (即未定义 `WX_UNICODE`)
|用户
|===

[WARNING]
====

如果 port 同时支持 Unicode 和普通版本， 请不要使用 `WX_UNICODE`。 如果希望默认启用 Unicode， 应定义 `WANT_UNICODE`。
====

[[wx-version-detection]]
=== 检测已安装的版本

要检测系统中安装的版本， 就需要定义 `WANT_WX`。 如果没有将其设置为特定的版本， 则组件将包含版本后缀。 `HAVE_WX` 变量在检测完成后会自动填入内容。

[[wx-ver-det-example]]
.检测已安装的 wxWidgets 版本和组件
[example]
====
下面的片段可以在安装 wxWidgets 的系统中令 port 使用它， 反之则作为一项选项提供。

[.programlisting]
....
WANT_WX=        yes

.include <bsd.port.pre.mk>

.if defined(WITH_WX) || ${HAVE_WX:Mwx-2.4} != ""
USE_WX=         2.4
CONFIGURE_ARGS+=--enable-wx
.endif
....

下面的片段在系统中有安装过时启用 wxPython 支持， 或在没有安装时作为选项提供； 对 wxWidgets 也是如此办理， 版本皆为 `2.6`。

[.programlisting]
....
USE_WX=         2.6
WX_COMPS=       wx
WANT_WX=        2.6

.include <bsd.port.pre.mk>

.if defined(WITH_WXPYTHON) || ${HAVE_WX:Mpython} != ""
WX_COMPS+=      python
CONFIGURE_ARGS+=--enable-wxpython
.endif
....

====

[[wx-defined-variables]]
=== 定义的变量

以下是一些可以在 port 中使用的变量 (这之前需要定义 <<wx-ver-sel-table>> 中的至少一个变量)。

.为使用 wxWidgets 的 port 定义的变量
[cols="1,1", frame="none", options="header"]
|===
| 变量名
| 说明

|`WX_CONFIG`
|到 wxWidgets `wx-config` 脚本的路径 (名字会随版本不同而不同)

|`WXRC_CMD`
|到 wxWidgets `wxrc` 程序的路径 (名字会随版本不同而不同)

|`WX_VERSION`
|将要用到的 wxWidgets 版本 (例如， `2.6`)

|`WX_UNICODE`
|如果没有定义， 而将会使用 Unicode 时， 系统将自动定义此变量。
|===

[[wx-premk]]
=== 在 [.filename]#bsd.port.pre.mk# 中进行处理

如果您需要在引用了 [.filename]#bsd.port.pre.mk# 之后立即对一些变量进行处理， 则需要定义 `WX_PREMK`。

[IMPORTANT]
====
如果定义了 `WX_PREMK`， 则在此 _之后_ 定义的依赖关系、 组件和变量将不会生效， 您在引用 [.filename]#bsd.port.pre.mk# 之前的 wxWidgets port 变量将直接起作用。
====

[[wx-premk-example]]
.在命令中使用 wxWidgets 变量
[example]
====
下面的片段以执行 `wx-config` 脚本来得到完整的版本号， 将其赋值到变量中， 并传递给一个程序举例说明了 `WX_PREMK` 的用法。

[.programlisting]
....
USE_WX=         2.4
WX_PREMK=       yes

.include <bsd.port.pre.mk>

.if exists(${WX_CONFIG})
VER_STR!=       ${WX_CONFIG} --release

PLIST_SUB+=     VERSION="${VER_STR}"
.endif
....

====

[NOTE]
====
在 target 中的 wxWidgets 变量可以直接使用， 而无需 `WX_PREMK` 的参与。
====

[[wx-additional-config-args]]
=== 额外的 `configure` 参数

某些 GNU `configure` 脚本在只设置了 `WX_CONFIG` 环境变量时， 无法自动找到 wxWidgets， 而需要使用额外的参数来加以指定。 您可以使用 `WX_CONF_ARGS` 变量来给出这些参数。

.可用于 `WX_CONF_ARGS` 的值
[cols="1,1", frame="none", options="header"]
|===
| 可用值
| 结果

|`absolute`
|`--with-wx-config=${WX_CONFIG}`

|`relative`
|`--with-wx=${LOCALBASE} --with-wx-config=${WX_CONFIG:T}`
|===

[[using-lua]]
== 使用 Lua

这一节描述了在 ports 系统中的 Lua 库的现状， 以及它与 ports 系统的集成。

[[lua-introduction]]
=== 介绍

许多不同版本的 Lua 库和相关的解释器之间是相互冲突的 (它们会安装同名的文件)。 在 ports 系统中， 这一问题是通过将不同版本的文件以不同的版本号作为后缀名解决的。

这样做最大的一个问题是， 每个程序都需要进行修改才能找到它所需要的版本。 不过， 通过将适当的参数传给编译器和连接器很容易解决这个问题。

[[lua-version]]
=== 选择版本

要让您的 port 使用指定版本的 Lua， 可以定义两个变量的值 (如果只定义了其中的一个， 则另一个会使用默认值)：

[[lua-ver-sel-table]]
.用于选择 Lua 版本的变量
[cols="1,1,1", frame="none", options="header"]
|===
| 变量
| 说明
| 默认值

|`USE_LUA`
|port 能够使用的 Lua 版本列表
|全部可用版本

|`USE_LUA_NOT`
|与 port 不兼容的版本列表
|无
|===

下面是目前 ports 系统提供的可用 Lua 版本和对应的目录：

.可用的 Lua 版本
[cols="1,1", frame="none", options="header"]
|===
| 版本
| Port

|`4.0`
|package:lang/lua4[]

|`5.0`
|package:lang/lua50[]

|`5.1`
|package:lang/lua[]
|===

在 <<lua-ver-sel-table>> 中的变量， 可以设置为下面的版本之一， 或用空格分隔的若干版本：

.指定 Lua 版本
[cols="1,1", frame="none", options="header"]
|===
| 说明
| 例子

|一个版本
|`4.0`

|某个版本或更高版本
|`5.0+`

|不高于某个版本
|`5.0-`

|版本范围 (低版本必须在前)
|`5.0-5.1`
|===

除此之外， 也有一些用来从可用版本中选择推荐版本的其它变量。 这些变量也可以设置为一组版本， 而前面的版本优先级较高。

.用于选择推荐 Lua 版本的变量
[cols="1,1", frame="none", options="header"]
|===
| 变量名
| 用于

|`WANT_LUA_VER`
|port

|`WITH_LUA_VER`
|用户
|===

[[lua-version-example]]
.选择 Lua 版本
[example]
====
下面是一个用到 Lua 版本 `5.0` 或 `5.1`， 并默认使用 `5.0` 的 port 的片段。 这个默认值可以通过 `WITH_LUA_VER` 来另外指定。

[.programlisting]
....
USE_LUA=      5.0-5.1
WANT_LUA_VER= 5.0
....

====

[[lua-components]]
=== 组件的选择

也有一些其它的应用， 尽管本身并不是 Lua 库， 但却与它们相关。 这些应用可以通过 `LUA_COMPS` 变量来指定。 可用的组件如下：

.可用的 Lua 组件
[cols="1,1,1", frame="none", options="header"]
|===
| 名字
| 说明
| 版本限制

|`lua`
|主库
|无

|`tolua`
|用于访问 C/C++ 代码的库
|`4.0-5.0`

|`ruby`
|Ruby 绑定
|`4.0-5.0`
|===

[NOTE]
====
还有一些其它的组件， 但这些组件是由解释器， 而不是由应用程序使用的 (也就是不被其它模块使用)。
====

每个组件的依赖关系类型可以通过手工添加分隔符为冒号的后缀来指定。 如果不指定， 则会采用默认类型 (请参见 <<lua-def-dep-types>>)。 以下是可用的依赖关系类型：

.可用的 Lua 依赖关系类型
[cols="1,1", frame="none", options="header"]
|===
| 名字
| 说明

|`build`
|这个组件是联编过程所必需的， 相当于 `BUILD_DEPENDS`

|`run`
|在运行时需要这个组件， 相当于 `RUN_DEPENDS`

|`lib`
|这个组件在联编和运行时都需要， 相当于 `LIB_DEPENDS`
|===

组件的默认依赖关系类型如下：

[[lua-def-dep-types]]
.默认的 Lua 依赖关系类型
[cols="1,1", frame="none", options="header"]
|===
| 组件
| 依赖关系类型

|`lua`
|对于 `4.0-5.0` 是 `lib` (动态连接) 而对于 `5.1` 则是 `build` (静态连接)

|`tolua`
|`build` (静态连接)

|`ruby`
|`lib` (动态连接)
|===

[[lua-components-example]]
.选择 Lua 组件
[example]
====
下面是一个使用了 Lua 版本 `4.0` 及其 Ruby 绑定的 port 片段。

[.programlisting]
....
USE_LUA=      4.0
LUA_COMPS=    lua ruby
....

====

[[lua-version-detection]]
=== 检测系统中已安装的版本

要检测系统中已安装的版本， 您必须定义 `WANT_LUA`。 如果没有将其设定为具体的版本， 则组件会包含版本后缀。 在检测之后， `HAVE_LUA` 变量将设为检测到的版本。

[[lua-ver-det-example]]
.检测已安装的 Lua 版本和组件
[example]
====
下面是一个如果系统中有安装 Lua 或选择了选项时使用它的 port 片段。

[.programlisting]
....
WANT_LUA=       yes

.include <bsd.port.pre.mk>

.if defined(WITH_LUA5) || ${HAVE_LUA:Mlua-5.[01]} != ""
USE_LUA=        5.0-5.1
CONFIGURE_ARGS+=--enable-lua5
.endif
....

下面的这段 port 在系统中已经有安装， 或用户选择了 tolua 和 Lua 支持时加以安装， 版本均选择 `4.0`。

[.programlisting]
....
USE_LUA=        4.0
LUA_COMPS=      lua
WANT_LUA=       4.0

.include <bsd.port.pre.mk>

.if defined(WITH_TOLUA) || ${HAVE_LUA:Mtolua} != ""
LUA_COMPS+=     tolua
CONFIGURE_ARGS+=--enable-tolua
.endif
....

====

[[lua-defined-variables]]
=== 定义的变量

在 port 中可以使用下列变量 (在定义了 <<lua-ver-sel-table>> 中至少一个变量之后)。

.为用到 Lua 的 port 定义的变量
[cols="1,1", frame="none", options="header"]
|===
| 变量名
| 说明

|`LUA_VER`
|将要使用的 Lua 版本。 (例如， `5.1`)

|`LUA_VER_SH`
|Lua 动态连接库的主版本 (例如， `1`)

|`LUA_VER_STR`
|不带点的 Lua 版本 (例如， `51`)

|`LUA_PREFIX`
|安装 Lua (及其组件) 使用的后缀

|`LUA_SUBDIR`
|在 [.filename]#${PREFIX}/bin#、 [.filename]#${PREFIX}/share# 和 [.filename]#${PREFIX}/lib# 中用于安装 Lua 的子目录

|`LUA_INCDIR`
|用以安装 Lua 和 tolua 头文件的目录

|`LUA_LIBDIR`
|用以安装 Lua 和 tolua 库文件的目录

|`LUA_MODLIBDIR`
|用以安装 Lua 模块动态连接库 ([.filename]#.so#) 的目录

|`LUA_MODSHAREDIR`
|用以安装 Lua 模块 ([.filename]#.lua#) 的目录

|`LUA_PKGNAMEPREFIX`
|Lua 模块包的后缀名

|`LUA_CMD`
|到 Lua 解释器的路径

|`LUAC_CMD`
|到 Lua 编译器的路径

|`TOLUA_CMD`
|到 tolua 程序的路径
|===

[[lua-variables-example]]
.告诉 port 到什么地方去找 Lua
[example]
====
下面的 port 片段展示了如何告诉使用的 configure 脚本去什么地方查找 Lua 的头文件和库文件。

[.programlisting]
....

USE_LUA=        4.0
GNU_CONFIGURE=  yes
CONFIGURE_ENV=  CPPFLAGS="-I${LUA_INCDIR}" LDFLAGS="-L${LUA_LIBDIR}"
....

====

[[lua-premk]]
=== 在 [.filename]#bsd.port.pre.mk# 时进行处理

如果您需要在使用引用 [.filename]#bsd.port.pre.mk# 之后就得到变量， 以便将其用于执行一些命令， 需要定义 `LUA_PREMK`。

[IMPORTANT]
====
如果您定义了 `LUA_PREMK`， 则在您引用 [.filename]#bsd.port.pre.mk#_之后_， 即使修改了 Lua port 变量， 版本和依赖关系也都不会随之发生变化了。
====

[[lua-premk-example]]
.在命令中使用 Lua 变量
[example]
====
下面的片段展示了如何利用 `LUA_PREMK`， 并运行 Lua 解释器得到完整的版本串， 将其赋值给一个变量， 并传递给程序。

[.programlisting]
....
USE_LUA=        5.0
LUA_PREMK=      yes

.include <bsd.port.pre.mk>

.if exists(${LUA_CMD})
VER_STR!=       ${LUA_CMD} -v

CFLAGS+=        -DLUA_VERSION_STRING="${VER_STR}"
.endif
....

====

[NOTE]
====
在 target 中的 Lua 变量可以在命令中安全的使用， 而无需使用 `LUA_PREMK`。
====

[[using-xfce]]
== 使用 Xfce

`USE_XFCE` 变量可以用来自动配置使用基于 Xfce 库或应用程序， 如 package:x11-toolkits/libxfce4gui[] 和 package:x11-wm/xfce4-panel[] 的 port 的依赖关系。

目前， 系统能够识别下列 Xfce 库和应用程序：

* libexo：package:x11/libexo[]
* libgui：package:x11-toolkits/libxfce4gui[]
* libutil：package:x11/libxfce4util[]
* libmcs：package:x11/libxfce4mcs[]
* mcsmanager：package:sysutils/xfce4-mcs-manager[]
* panel：package:x11-wm/xfce4-panel[]
* thunar：package:x11-fm/thunar[]
* wm：package:x11-wm/xfce4-wm[]
* xfdev：package:dev/xfce4-dev-tools[]

除此之外， 还能够使用下列参数：

* configenv： 如果您的 port 需要使用特殊的 `CONFIGURE_ENV` 来查找所需的库。 
+
[.programlisting]
....
-I${LOCALBASE}/include -L${LOCALBASE}/lib
....

会加到 `CONFIGURE_ENV` 的 CPPFLAGS。

因此， 如果 port 有到 package:sysutils/xfce4-mcs-manager[] 的依赖关系， 并需要在 configure 的环境中指定特殊的饿 CPPFLAGS， 则所用的语法为：

[.programlisting]
....
USE_XFCE=        mcsmanager configenv
....

[[using-mozilla]]
== 使用 Mozilla

.用到 Mozilla 的 port 使用的变量
[cols="1,1", frame="none"]
|===
|`USE_GECKO`
|port 支持的 Gecko 后端。 可选值： `libxul` ([.filename]#libxul.so#)、 `seamonkey` ([.filename]#libgtkembedmoz.so#， 过时， 新 port 应避免使用)。

|`USE_FIREFOX`
|port 需要使用 Firefox 作为运行环境依赖。 可选值： `yes` (使用默认版本)、 `40`、 `36`、 `35`。 默认的依赖采用的是版本 `40`。

|`USE_FIREFOX_BUILD`
|port 需要使用 Firefox 作为联编环境依赖。 可选值： 参见 USE_FIREFOX。 这个变量会自动设置 USE_FIREFOX 使用相同的值。

|`USE_SEAMONKEY`
|port 需要使用 SeaMonkey 作为运行环境依赖。 可选值： `yes` (使用默认版本)、 `20`、 `11` (过时， 新 port 应避免使用)。 默认的依赖采用的是版本 `20`。

|`USE_SEAMONKEY_BUILD`
|port 需要使用 SeaMonkey 作为联编环境依赖。 可选值： 参见 USE_SEAMONKEY。 这个变量会自动设置 USE_SEAMONKEY 使用相同的值。

|`USE_THUNDERBIRD`
|port 需要使用 Thunderbird 作为运行环境依赖。 可选值： `yes` (使用默认版本)、 `31`、 `30` (过时， 新 port 应避免使用)。 默认的依赖采用的是版本 `31`。

|`USE_THUNDERBIRD_BUILD`
|port 需要使用 Thunderbird 作为联编环境依赖。 可选值： 参见 USE_THUNDERBIRD。 这个变量会自动设置 USE_THUNDERBIRD 使用相同的值。
|===

可用变量的完整列表， 请参阅 [.filename]#/usr/ports/Mk/bsd.gecko.mk#。

[[using-databases]]
== 使用数据库

.ports 中有关数据库的变量
[cols="1,1", frame="none", options="header"]
|===
| Variable
| Means

|`USE_BDB`
|如果这个变量为 `yes`， 则把 package:databases/db41[] 列为依赖关系。 这个变量还可以被设置成的值有： 40，41， 42、 43、 44、 46、 47、 48 或 51。 您可以声明可接受值的范围， `USE_BDB`=42+ 将寻找已安装的最高版本， 如果没有找到则退回到 42。

|`USE_MYSQL`
|如果这个变量为 `yes`， 则把 package:databases/mysql55-server[] 列为依赖关系。还有一个相关的变量，`WANT_MYSQL_VER`, 可以设置的值有 323，40，41，50，51， 52， 55 或者 60。

|`USE_PGSQL`
|如果设置成 `yes`，则把 package:databases/postgresql82[] 列为依赖关系。还有一个相关的变量，`WANT_PGSQL_VER`， 可以设置的值有 73，74，80，81，82， 83 或 90。
|===

更多详情请参阅 http://www.freebsd.org/cgi/cvsweb.cgi/ports/Mk/bsd.database.mk[ bsd.database.mk]。

[[rc-scripts]]
== 启动和停止服务 (rc 脚本)

[.filename]#rc.d# 脚本在系统启动时用于启动服务， 并为管理员提供停止、 启动和重新启动某个服务的标准方法。 Ports 安装的脚本会集成到系统的 [.filename]#rc.d# 框架中。 关于如何使用它的说明， 可以在 extref:{handbook}config-tuning/[使用手册的 rc.d 章节, configtuning-rcd] 找到。 关于可用命令的详细解释， 则可以在 man:rc[8] 和 man:rc.subr[8] 找到。 最后， 您可以参阅 extref:{rc-scripting}[这篇文章] 了解撰写 [.filename]#rc.d# 脚本的最佳实践。

可以安装一或多个 [.filename]#rc.d# 脚本：

[.programlisting]
....
USE_RC_SUBR=	doormand
....

这些脚本必须放到 [.filename]#files# 目录， 并附加 `.in`。 这个文件中可以使用标准的 `SUB_LIST` 替换展开。 除此之外， 我们还强烈推荐使用 `%%PREFIX%%` 和 `%%LOCALBASE%%` 替换展开。 关于 `SUB_LIST` 的介绍可以在 <<using-sub-files,本书的相关章节>> 找到。

在 FreeBSD 6.1-RELEASE 之前， 与 man:rcorder[8] 的集成是通过 `USE_RCORDER` 而不是 `USE_RC_SUBR` 来完成的。 不过， 除非 port 需要提供安装进基本系统这样的选项， 或者服务需要在 [.filename]#rc.d# 脚本 [.filename]#FILESYSTEMS# 之前运行这类特殊情况， 一般来说是不需要使用这个功能的。

从 FreeBSD 6.1-RELEASE 开始， 本地安装的 [.filename]#rc.d# 脚本 (包括由 port 安装的脚本) 会纳入基本系统的 man:rcorder[8]。

以下是一个简单的 [.filename]#rc.d# 脚本：

[.programlisting]
....
#!/bin/sh

# $FreeBSD$
#
# PROVIDE: doormand
# REQUIRE: LOGIN
# KEYWORD: shutdown
#
# 在 /etc/rc.conf.local 或 /etc/rc.conf 中增加下述设置可以启用这一服务：
#
# doormand_enable (bool):	默认设为 NO。
#				设为 YES 可以启用 doormand。
# doormand_config (path):	默认设为 %%PREFIX%%/etc/doormand/doormand.cf。
#

. /etc/rc.subr

name="doormand"
rcvar=${name}_enable

command=%%PREFIX%%/sbin/${name}
pidfile=/var/run/${name}.pid

load_rc_config $name

: ${doormand_enable="NO"}
: ${doormand_config="%%PREFIX%%/etc/doormand/doormand.cf"}

command_args="-p $pidfile -f $doormand_config"

run_rc_command "$1"
....

除非有很站得住脚的理由提前启动服务，所有的 ports 脚本应使用 

[.programlisting]
....
REQUIRE: LOGIN
....

。 如果服务需要以特定用户 (除 root 之外) 身份启动， 则必须这样做。 在前面的例子中， 我们还使用了 

[.programlisting]
....
KEYWORD: shutdown
....

以便让 mythical port 在系统停机的过程中以正常的方式终止， 因为它需要在系统引导过程中启动服务。 如果脚本没有启动任何服务， 则并不需要这样做。

这里， 对变量的默认赋值方法应采用 "="， 而非 ":=" 这样的形式。 这是因为， 前一种赋值方法只有在变量未被设置时才设置默认值， 而后一种方法则会在变量没有设置， _或者_ 其值为空时都设置默认值。 用户非常可能在其 [.filename]#rc.conf.local# 中使用类似 
[.programlisting]
....
doormand_flags=""
....

这样的设置， 而采用 ":=" 来进行赋值， 则会在不经意间覆盖用户所希望的设置。

[NOTE]
====
新增的脚本均不应使用 [.filename]#.sh# 后缀。 未来， 仍然包含这一后缀的脚本将被批量改名。
====

=== 卸载时停止服务

可以在卸载的过程中自动地停止服务。 我们建议只有在绝对必要， 例如必须在删除文件之前停止服务这类的情况下才使用这一功能。 通常来说， 决定是否在卸载时停止服务是系统管理员需要考虑的事情。 另外要注意， 这个功能也会影响升级过程。

需要时可以在 [.filename]#pkg-plist# 中加入：

[.programlisting]
....
@stopdaemon doormand
....

这里的参数必须与 `USE_RC_SUBR` 变量的内容匹配。

[[users-and-groups]]
== 添加用户和用户组

一些 port 需要在安装的系统中创建特定的用户或用户组。 如果有这种情况， 请从 50 到 999 之间选择一个尚未使用的 UID， 并在 [.filename]#ports/UIDs# (针对用户) 或 [.filename]#ports/GIDs# (针对组) 中予以记录。 请务必确保您没有使用系统中已经在其他 ports 中使用的 UID。

如果您的 port 需要创建新用户或用户组， 请在提交补丁的时候一并提交这两个文件的补丁。

接下来， 可以在您的 [.filename]#Makefile# 中使用 `USERS` 和 `GROUPS` 这两个变量， 系统会在安装时自动创建用户或组。

[.programlisting]
....
USERS=	pulse
GROUPS=	pulse pulse-access pulse-rt
....

现有的保留 UID 和 GID 列表， 可以在 [.filename]#ports/UIDs# 和 [.filename]#ports/GIDs# 找到。

== 依赖内核源代码的 Ports

某些 ports (例如可加载式内核模块) 需要内核的源文件才能编译。 下面是检测用户是否安装了源代码的例子：

[.programlisting]
....
.if !exists(${SRC_BASE}/sys/Makefile)
IGNORE=         requires kernel sources to be installed
.endif
....
