---
title: 章 3. 打造 Port 快速上手篇
prev: books/porters-handbook/new-port
next: books/porters-handbook/slow-porting
---

[[quick-porting]]
= 打造 Port 快速上手篇
:doctype: book
:toc: macro
:toclevels: 1
:icons: font
:sectnums:
:source-highlighter: rouge
:experimental:
:skip-front-matter:
:toc-title: 目录
:part-signifier: 部分
:chapter-signifier: 第
:appendix-caption: 附录
:table-caption: 表
:figure-caption: 图
:example-caption: 例 
:xrefstyle: basic
:relfileprefix: ../
:outfilesuffix:
:sectnumoffset: 3

include::shared/mirrors.adoc[]
include::shared/authors.adoc[]
include::shared/releases.adoc[]
include::shared/zh-tw/mailing-lists.adoc[]
include::shared/zh-tw/urls.adoc[]

toc::[]

本節主要介紹如何來快速打造 port，然而實際應用時這快速方法可能不足，完整的 "慢速打造 Port" 的步驟在 <<slow-porting>> 詳述。

首先取得該應用程式的原始程式碼壓縮檔(tarball)，並把它放到 `DISTDIR`，預設路徑應該是 [.filename]#/usr/ports/distfiles#.

[NOTE]
====
這些步驟假設軟體可以直接編譯。也就是不需要任何修改就可以直接在 FreeBSD 上執行。如果需要修改，請參見<<slow-porting>>。
====

[NOTE]
====
It is recommended to set the `DEVELOPER` man:make[1] variable in [.filename]#/etc/make.conf# before getting into porting.

[source,shell]
....

# echo DEVELOPER=yes >> /etc/make.conf
....

This setting enables the "developer mode" that displays deprecation warnings and activates some further quality checks on calling `make`.
====

[[porting-makefile]]
== 編寫 [.filename]#Makefile#

最簡單的 [.filename]#Makefile# 大概是像這樣：

[.programlisting]
....
# $FreeBSD: head/zh_TW.UTF-8/books/porters-handbook/book.xml 48496 2016-03-29 01:37:53Z kevlo $

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

MAINTAINER=	youremail@example.com
COMMENT=	Cat chasing a mouse all over the screen

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

[NOTE]
====
In some cases, the [.filename]#Makefile# of an existing port may contain additional lines in the header, such as the name of the port and the date it was created. This additional information has been declared obsolete, and is being phased out.
====

嗯，大致就是這樣，看看你已經領略多少了呢？ 看到 `$FreeBSD: head/zh_TW.UTF-8/books/porters-handbook/book.xml 48496 2016-03-29 01:37:53Z kevlo $` 這一行的話，別想太多 ，當該 port 正式進入 port tree 時， Subversion 就會自動轉換為相關字串囉。 有關這點的細節部份，可以參閱 <<porting-samplem,sample Makefile>> 章節。

[[porting-desc]]
== 撰寫說明檔

無論是否打算再加工做成 package，有兩個檔案是任何 port 都必須要具備的。 這兩個檔分別是 [.filename]#pkg-descr# 及 [.filename]#pkg-plist# 。 他們檔名前面都有 [.filename]#pkg-# 以跟其他檔案做區別。

[[porting-pkg-descr]]
=== [.filename]#pkg-descr#

這是此 port 的詳細說明檔，請用一段或幾段文字來說明該 port 的作用

[NOTE]
====
請注意，這檔_絕非_「該軟體的說明手冊」或是「如何編譯、使用該 port 的說明」！ _若是從該軟體的 [.filename]#README# 或 manpage 直接複製過來的話，請注意_。他們常常不是正確的 port 描述或是格式並不適合。例如，manpage會對齊空白，這用monospace字型來看會特別糟糕。
====

A well-written [.filename]#pkg-descr# describes the port completely enough that users would not have to consult the documentation or visit the website to understand what the software does, how it can be useful, or what particularly nice features it has. Mentioning certain requirements like a graphical toolkit, heavy dependencies, runtime environment, or implementation languages help users decide whether this port will work for them.

Include a URL to the official WWW homepage. Prepend _one_ of the websites (pick the most common one) with `WWW:` (followed by single space) so that automated tools will work correctly. If the URI is the root of the website or directory, it must be terminated with a slash.

[NOTE]
====
If the listed webpage for a port is not available, try to search the Internet first to see if the official site moved, was renamed, or is hosted elsewhere.
====

這是 [.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/
....

[[porting-pkg-plist]]
=== [.filename]#pkg-plist#

這是該 port 所會裝的所有檔案清單，另外因為 package 會由這清單所產生，因此也被稱為『"packing list (打包清單)"』。路徑是相對於安裝的 prefix (通常是 [.filename]#/usr/local# )。

這是一個簡單的例子：

[.programlisting]
....
bin/oneko
man/man1/oneko.1.gz
lib/X11/app-defaults/Oneko
lib/X11/oneko/cat1.xpm
lib/X11/oneko/cat2.xpm
lib/X11/oneko/mouse.xpm
....

關於 packing list 方面，可以詳閱 man:pkg-create[8] manual page 。

[NOTE]
====
建議清單內的檔名，依照字母順序作排序，那麼下次要升級時， 會比較清楚、方便來更新這份清單。 
====

[TIP]
====

手動產生這份清單實在太苦了。尤其若該 port 會裝一大堆檔案的話， 請多善用 <<plist-autoplist,自動產生 packing list>> 會比較省時省力唷。
====

只有在一種情況下可以省略 [.filename]#pkg-plist# 檔： 若安裝的 port 相當單純，只有裝一些檔案，那麼可以在 [.filename]#Makefile# 內改用 `PLIST_FILES` 來取代。 比如，可以在上述的 [.filename]#oneko# port 內不必附上 [.filename]#pkg-plist# ，而只需在 [.filename]#Makefile# 內加入下列幾行：

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

[NOTE]
====
Usage of `PLIST_FILES` should not be abused. When looking for the origin of a file, people usually try to grep through the [.filename]#pkg-plist# files in the ports tree. Listing files in `PLIST_FILES` in the [.filename]#Makefile# makes that search more difficult.
====

[TIP]
====

If a port needs to create an empty directory, or creates directories outside of [.filename]#${PREFIX}# during installation, refer to <<plist-dir-cleaning>> for more information.
====

然而，使用這個方法列出 port 的檔案和目錄是必須付出代價： 不能使用 man:pkg-create[8] 和 <<plist-keywords>> 描述的關鍵字。 因此，這招僅適用於較簡單的 port ，以及簡化該 port 的作法。 此外，這招還有一個好處：可以減少 ports collection 的整體檔案總數。 所以，在考慮是否要用 [.filename]#pkg-plist# 之前， 可以先斟酌這個替代方案看看。

後面會介紹到如何運用 [.filename]#pkg-plist#、 `PLIST_FILES` 這些技巧以因應<<plist,更複雜的狀況>>。

[[porting-checksum]]
== 產生 checksum 檔

只要打 `make makesum` 就好了， 接下來就會自動產生相對應的 [.filename]#distinfo# 檔了唷 。

[[porting-testing]]
== 測試 Port

接下來，必須檢驗是否有符合 port 的遊戲規則，包括打包該 port 為 package。 以下有幾個需要確認的重要地方：

* 若該 port 沒裝的東西，不要列在 [.filename]#pkg-plist# 內。
* 若該 port 有裝的東西，請務必列在 [.filename]#pkg-plist# 內。
* The port can be installed using the `install` target. This verifies that the install script works correctly.
* The port can be deinstalled properly using the `deinstall` target. This verifies that the deinstall script works correctly.
* The port does not access network resources after the `fetch` target. This is important for package builders, such as package:ports-mgmt/poudriere[].
* Make sure that `make package` can be run as a normal user (that is, not as `root`). If that fails, `NEED_ROOT=yes` must be added to the port [.filename]#Makefile#.

[.procedure]
====
*Procedure: 建議的測試順序*

. `make stage`
. `make check-orphans`
. `make package`
. `make install`
. `make deinstall`
. `pkg add _package-filename_`
. `make package` (as user)
====

確認在任何階段都沒有任何警告出現。

Thorough automated testing can be done with package:ports-mgmt/tinderbox[] or package:ports-mgmt/poudriere[] from the Ports Collection. These applications maintain `jails` where all of the steps shown above can be tested without affecting the state of the host system.

[[porting-portlint]]
== 以 `portlint` 來作檢查 Port

請用 `portlint` 來檢查該 port 是否有遵循我們的規則。 package:ports-mgmt/portlint[] 是 ports collection 的其中一個套件。 它主要可以用來檢驗 <<porting-samplem,Makefile>> 內容是否正確以及 <<porting-pkgname,package>> 是否有正確命名。

[[porting-submitting]]
== 提交新的 Port

提交新的 Port 前，請閱讀 <<porting-dads,DOs and DON'Ts>> 章節。

現在你很高興終於打造出 port 來囉，唯一剩下要做的就是把它正式放到 FreeBSD ports tree 內，才能讓每個人都能分享使用這個 port。 我們不需要 [.filename]#work# 目錄或是檔名像 [.filename]#pkgname.tgz# 的 package ，請現在刪除他們。

Next, build the man:shar[1] file. Assuming the port is called `oneko`, `cd` to the directory above where the `oneko` directory is located, and then type: `shar find oneko > oneko.shar`

To submit [.filename]#oneko.shar#, use the https://bugs.freebsd.org/submit/[bug submit form] (category `Ports Tree`). Add a short description of the program to the Description field of the PR (perhaps a short version of `COMMENT`), and do not forget to add [.filename]#oneko.shar# as an attachment.

[NOTE]
====
Giving a good description in the summary of the problem report makes the work of port committers a lot easier. We prefer something like "New port: _category_/_portname__short description of the port_" for new ports. Using this scheme makes it easier and faster to begin the work of committing the new port.
====

再次強調一點：_不必附上原始 source 的 distfile ，也就是 [.filename]#work# 目錄。 同時，也不必附上 `make package` 時產生的 package_。新的 port 請使用 man:shar[1] ，不要用 man:diff[1] 。

送出 port 之後，請耐心等候佳音。 有時候可能需要等個幾天或幾個月時間，才會在 FreeBSD ports tree 上正式出現。 等待中的 port PR 清單可以在 http://www.FreeBSD.org/cgi/query-pr-summary.cgi?category=ports[] 查閱。

在看過新的 port 之後，如果需要的話，我們會回覆您，然後會將它提交到 port tree 。 您的大名會被列在 link:{contributors}#contrib-additional[Additional FreeBSD Contributors] 列表上，以及其他檔案中。

