---
title: 第 3 章 简单的 port
prev: books/porters-handbook/own-port
next: books/porters-handbook/slow
showBookMenu: true
weight: 3
params:
  path: "/books/porters-handbook/quick-porting/"
---

[[quick-porting]]
= 简单的 port
:doctype: book
:toc: macro
:toclevels: 1
:icons: font
:sectnums:
:sectnumlevels: 6
:sectnumoffset: 3
: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。 很多时候， 这点内容是不够的， 您需要阅读这份文档中更深入的内容。

首先， 需要取得包含源代码的 tar包， 并把它放到 ``DISTDIR``变量所指的地方。 默认的情况下， 这应该是 [.filename]#/usr/ports/distfiles#。

[NOTE]
====
下面的内容假定您不需要修改软件的源代码就能在 FreeBSD 上编译通过。 如果需要修改代码， 就需要参考下一章的内容了。
====

[[porting-makefile]]
== 编写 [.filename]#Makefile#

最简单的 [.filename]#Makefile# 应该是这个样子的：

[.programlisting]
....
# New ports collection makefile for:   oneko
# Date created:        5 December 1994
# Whom:                asami
#
# $FreeBSD$
#

PORTNAME=      oneko
PORTVERSION=   1.1b
CATEGORIES=    games
MASTER_SITES=  ftp://ftp.cs.columbia.edu/archives/X11R5/contrib/

MAINTAINER=    asami@FreeBSD.org
COMMENT=       A cat chasing a mouse all over the screen

MAN1=          oneko.1
MANCOMPRESSED= yes
USE_IMAKE=     yes

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

看看您是否能够看懂。 不必担心 `$FreeBSD$` 那一行， 当这个 port 被导入到 ports 树里的时候， CVS 会自动填写它。 您可以在 <<porting-samplem, 示范的 Makefile>>那章找到更多的细节。

[[porting-desc]]
== 创建描述文件

有 2 个描述文件对于任何一个 port 来说是必须的， 不论它是不是打算成为 package。 它们是 [.filename]#pkg-descr# 和 [.filename]#pkg-plist#。 这两个文件使用 [.filename]#pkg-# 前缀以区别于其它文件。

=== [.filename]#pkg-descr# (关于 port 的冗长描述文件)

这是 port 里一个较长的描述文件。 使用一段或几段文件文字来简明的描述这个 ports 是用来做什么的。

[NOTE]
====
这 _不是_ 手册或者对如何 深入使用/编译这个port的说明！ _要是您从 [.filename]#README# 或者联机手册里面中复制文字的话， 请务必小心_； 通常， 它们不是对这个 port 简明扼要的描述， 或者用了难以使用的格式 (比如， 联机手册里有迫使两端对齐的空格)。 如果要移植的软件有官方的WWW网页， 您应该在这里列出来。 使用 `WWW:` 作为前缀来表示 __一个__网站， 这样其它的自动工具就能正常工作了。
====

下面是一个简单的 [.filename]#pkg-descr# 例子：

[.programlisting]
....
This is a port of oneko, in which a cat chases a poor mouse all over
the screen.
 :
(etc.)

WWW: http://www.oneko.org/
....

=== [.filename]#pkg-plist# (port 的装箱单)

这份文件列出了 port 所要安装的所有文件。 由于 package 也是据此进行打包， 因此它也被称作 "装箱单(packing list)". 这个文件中， 路径是相对于安装的路径的 (通常是 [.filename]#/usr/local# 或 [.filename]#/usr/X11R6#)。 如果您使用 `MAN__n__` 变量的话， 请不要在这里列出任何联机手册。 假如 port 在安装过程中会创建一些目录， 请务必增加对应的 `@dirrm` 行， 以便在 package 被卸载时予以自动删除。

下面是一个简单的例子：

[.programlisting]
....
bin/oneko
lib/X11/app-defaults/Oneko
lib/X11/oneko/cat1.xpm
lib/X11/oneko/cat2.xpm
lib/X11/oneko/mouse.xpm
@dirrm lib/X11/oneko
....

参考 man:pkg_create[1] 的联机手册以获得更多有关装箱单的细节

[NOTE]
====
建议您将这个文件里的所有的文件名按字母排序。 这样， 在升级这个port的时候就能够更方便地核实所做的修改。
====

[NOTE]
====
手工创建这样一份列表可能是一件非常枯燥的事情。 如果您的 port 需要安装大量的文件， <<plist-autoplist,自动创建装箱单>> 会帮您省下不少时间。
====

只有一种情况可以不用 [.filename]##pkg-plist##文件。 如果这个 port 只安装很少量的一些文件或目录的话， 这些文件和目录就可以分别列在 [.filename]##Makefile## 的 ``PLIST_FILES``和``PLIST_DIRS`` 变量里。 举个例子来说， 我们可以在上面那个 [.filename]##oneko## port 里面不用 [.filename]##pkg-plist##， 而把下面的这几行加到 [.filename]##Makefile## 里面：

[.programlisting]
....
PLIST_FILES=    bin/oneko \
                lib/X11/app-defaults/Oneko \
                lib/X11/oneko/cat1.xpm \
                lib/X11/oneko/cat2.xpm \
                lib/X11/oneko/mouse.xpm
PLIST_DIRS=     lib/X11/oneko
....

当然， 如果一个 port 不需要给它自己创建目录的话， 就不用设置 `PLIST_DIRS` 变量了。

不过， 如果用这种方式来列出 port 要安装的文件和目录的话， 也就无法利用在 man:pkg_create[1] 里介绍的命令来制作 package 了。 因此， 这种方法只适用于那些简单的 port， 使它们更为简化。 同时， 这种做法也有助于减少 ports collection 中的文件数量。 在采用 [.filename]#pkg-plist# 之前， 请考虑一下使用这种方法。

稍后我们将看到 [.filename]#pkg-plist# 以及 `PLIST_FILES` 如何处理 <<plist,更复杂的任务>>。

[[porting-checksum]]
== 创建校验和文件

只要键入 `make makesum`， port 便会自动创建 [.filename]##distinfo##文件。

如果下载的文件的校验和经常变化， 而您又能确保它们的来源可靠 (比如， 来自于CD制造商， 或每天联编生成的文档文件)， 就应该在 `IGNOREFILES` 里面标明这些文件。 这样， 再运行 `make makesum` 的时候便不会把这些标记 `IGNORE` 的文件计算在内了。

[[porting-testing]]
== 测试 port

应当确定您的 port 确实做了您希望它们做的事情， 包括打包。下面是需要重点检查的一些重要的工作。

* [.filename]#pkg-plist# 中没有包括任何不想安装的文件
* [.filename]#pkg-plist# 包含了所有应该安装的文件
* 您的 port 能够使用 `reinstall` 多次安装。
* 您的 port 能在卸载 (deinstall) 时， 自动完成 <<plist-cleaning,清理>>

[.procedure]
====
*Procedure: 推荐的测试顺序*

. `make install`
. `make package`
. `make deinstall`
. `pkg_add package-name`
. `make deinstall`
. `make reinstall`
. `make package`
====

确信在 `package` 和 `deinstall` 阶段没有任何警告。 第三步以后， 检查是否所有新建的目录都被正确删除了。 在第四步以后， 试着运行一下所装的软件， 确保当它以 package 方式安装的时候也能正常工作。

自动化这些步骤最简单的方法是通过 ports tinderbox 来进行测试。 它可以维护 `jails` 并在其中完成全部测试工作， 而不会破坏正在运行的系统的状态。 请参见 [.filename]#ports/ports-mgmt/tinderbox# 以了解更多的信息。

[[porting-portlint]]
== 用 `portlint` 来检查 port

请使用 `portlint` 命令来检查您的 port 是否符合我们的规范。 package:ports-mgmt/portlint[] 程序是 ports 套件的一部分。 这个程序的主要功能是帮助您检查 <<porting-samplem,Makefile>> 的样式是否符合规范， 以及 <<porting-pkgname,package>> 的命名是否得体。

[[porting-submitting]]
== 提交新 port

在提交新 port 之前， 应先阅读 <<porting-dads, 该做什么和不该做什么>> 一节。

既然已经对所制作的 port 相当满意了， 剩下的工作， 便是将它放进 FreeBSD 的主 ports 树， 以便让更多的人从中受益。 我们并不需要您的 [.filename]#work# 目录以及 [.filename]#pkgname.tgz# 包， 因此现在可以删除它们了。 假定您的 port 的名字是 oneko， 接下来要做的是 `cd` 到 `oneko` 所在的目录， 然后输入命令： `shar find oneko > oneko.shar`

将这个 `oneko.shar` 文件作为附件， 使用 man:send-pr[1] 程序提交 (请参阅 extref:{contributing}[Bug Reports and General Commentary, CONTRIB-GENERAL] 以了解关于 man:send-pr[1] 的进一步详情) 将其送出。 请务必将您的 bug 报告分类 (category) 为 `ports` 并把子分类 (class) 设置为 `change-request` (不要把报告表及为机密的， 即 `confidential`！)。 此外， 在 PR 的描述 ("Description") 一栏中的内容应该是 port 的简要介绍 (例如 `COMMENT` 内容的简化版本)， 而 shar 文件则应填入修正 ("Fix") 栏中。

[NOTE]
====
在问题报告里面使用了一段好的描述， 能使我们的工作变得更容易。 习惯上， 我们会使用类似： "New port: <category>/<portname> <short description of the port>" 这样的标题来说明这是新的 port。 如果您也使用这样的习惯， 那么我们将更容易更方便地阅读您的 PR， 从而加快处理速度。
====

再次声明， __不要包含原始的distfile， [.filename]##work##目录， 或者您用 `make package` 制作的包__； 此外， 对于新的 port 请务必使用 man:shar[1] 而不是 man:diff[1]。

在您提交的您的 port 以后请耐心等待。 有时在一个 port 正式加入 FreeBSD 之前需要花费好几个月， 尽管也有可能是几天。 您可以查看 http://www.FreeBSD.org/cgi/query-pr-summary.cgi?category=ports[ 正等待被 commit 到 FreeBSD 的 port PR]。

一旦我们看过了您的报告， 有必要的话我们会联系您， 并把它放到 ports 树里。 您的名字也会出现在 extref:{contributors}[Additional FreeBSD Contributors, contrib-additional] 和其它的文件。 不是很棒吗!?  :-)
