--- title: 章 3. 打造 Port 快速上手篇 prev: books/porters-handbook/new-port next: books/porters-handbook/slow-porting 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,然而實際應用時這快速方法可能不足,完整的 "慢速打造 Port" 的步驟在 crossref:slow-porting[slow-porting,Slow Porting] 詳述。 首先取得該應用程式的原始程式碼壓縮檔(tarball),並把它放到 `DISTDIR`,預設路徑應該是 [.filename]#/usr/ports/distfiles#. [NOTE] ==== 這些步驟假設軟體可以直接編譯。也就是不需要任何修改就可以直接在 FreeBSD 上執行。如果需要修改,請參見crossref:slow-porting[slow-porting,Slow Porting]。 ==== [NOTE] ==== 在 porting 之前,建議在 [.filename]#/etc/make.conf# 設定 `DEVELOPER` man:make[1] 變數。 [source,shell] .... # echo DEVELOPER=yes >> /etc/make.conf .... 這個設定開啟了 "developer mode" ,顯示已棄用警告並在使用 `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 .... 嘗試了解此檔案,有關這點的細節部份,可以參閱 crossref:porting-samplem[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字型來看會特別糟糕。 另一方面, [.filename]#pkg-descr# 的內容必須比 crossref:makefiles[makefile-comment,COMMENT line from the Makefile] 還要詳細,要能詳細解釋此 port 相關的內容。 ==== 一個良好的 [.filename]#pkg-descr# 可以讓使用者清楚的了解軟體的功能而無須查詢文件或者訪問網站,提及特定的需求像是圖形工具、依賴、執行的環境跟實作的語言,能大大的幫助使用者了解這個 port 是怎麼運作的。 [NOTE] ==== 過去在 #pkg-descr# 文件最後一行引入的 URL 已經移到 [.filename]#Makefile# 裡面了。 ==== [[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 會裝一大堆檔案的話, 請多善用 <> 會比較省時省力唷。 ==== 只有在一種情況下可以省略 [.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] ==== `PLIST_FILES` 的使用不應該被濫用,人們通常透過在 ports tree 的 [.filename]#pkg-plist# 文件來了解 port ,在 [.filename]#Makefile# 中使用 `PLIST_FILES` 敘述會增加搜尋的難度。 ==== [TIP] ==== 如果 port 需要創建空的目錄,或者安裝時在 [.filename]#${PREFIX}# 之外創建目錄,請參考 crossref:plist[plist-dir-cleaning, Cleaning Up Empty Directories] 來獲得更多資訊。 ==== [TIP] ==== 因為 `PLIST_FILES` 是 man:make[1] 的變數,任何在此條目的 sapce 都必須被引入。舉例來說,如果使用 man:pkg-create[8] 和 crossref:plist[plist-keywords, Expanding Package List with Keywords] 描述的關鍵字,以下的條目必須被引入。 [.programlisting] .... PLIST_FILES= "@sample ${ETCDIR}/oneko.conf.sample" .... ==== 後面會介紹到如何運用 [.filename]#pkg-plist#、 `PLIST_FILES` 這些技巧以因應crossref:plist[plist,更複雜的狀況]。 [[porting-checksum]] == 產生 checksum 檔 只要打 `make makesum` 就好了, 接下來就會自動產生相對應的 [.filename]#distinfo# 檔了唷 。 [[porting-testing]] == 測試 Port 接下來,必須檢驗是否有符合 port 的遊戲規則,包括打包該 port 為 package。 以下有幾個需要確認的重要地方: * 若該 port 沒裝的東西,不要列在 [.filename]#pkg-plist# 內。 * 若該 port 有裝的東西,請務必列在 [.filename]#pkg-plist# 內。 * port 可以透過 `install` 來安裝,這可以確保安裝的 script 是正常運作的。 * port 可以透過 `uninstall` 來移除,這可以確保安裝的 script 是正常運作的。 * port 只有在 `featch` 目標時才能使用網路,這對 package builders 很重要,像是 package:ports-mgmt/poudriere[]. * 確保 `make package` 可以被一般使用者執行 (也就是說,非 `root` 使用者),如果上述執行失敗,軟體很可能需要修改,請參考 crossref:uses[uses-fakeroot,`fakeroot`] 和 crossref:uses[uses-uidfix,`uidfix`]。 [.procedure] ==== *Procedure: 建議的測試順序* . `make stage` . `make check-orphans` . `make package` . `make install` . `make deinstall` . `pkg add _package-filename_` . `make package` (as user) ==== 確認在任何階段都沒有任何警告出現。 可以透過 package:ports-mgmt/tinderbox[] 或者 Ports Collection 的 package:ports-mgmt/poudriere[] 工具來完成自動化測試,參考 crossref:testing[testing-poudriere,Poudriere] 獲得更多的資訊。她維護 `jails` ,可以在不影響系統的情況下執行上述所有的測試。 [[porting-portlint]] == 以 `portlint` 來作檢查 Port 請用 `portlint` 來檢查該 port 是否有遵循我們的規則。 package:ports-mgmt/portlint[] 是 ports collection 的其中一個套件。 它主要可以用來檢驗 <> 內容是否正確以及 <> 是否有正確命名。 [IMPORTANT] ==== 不要盲目的相信 `portlint` 的輸出,他是一個 static lint 工具,並且有可能會出錯。 ==== [[porting-submitting]] == 提交新的 Port 提交新的 Port 前,請閱讀 <> 章節。 現在你很高興終於打造出 port 來囉,唯一剩下要做的就是把它正式放到 FreeBSD ports tree 內,才能讓每個人都能分享使用這個 port。 [IMPORTANT] ==== 我們不需要 [.filename]#work# 目錄或是檔名像 [.filename]#pkgname.tgz# 的 package ,請現在刪除他們。 ==== 下一步,創建一個 man:patch[1] ,一個文件,假設此 port 叫做 `oneko` 並且屬於 `games` 類別。 [[porting-submitting-diff]] .為新的 Port 創建 [.filename]#.diff# [example] ==== 透過 `git add .` 加入所有的檔案,然後透過 `git diff` 來檢查不同處,如下。 [source,shell] .... % git add . % git diff --staged .... 確保所有需要的檔案都被引入了,將更改提交到你本地分支並使用 `git format-patch` 產生 patch。 [source,shell] .... % git commit % git format-patch origin/main .... 使用 `git format-patch` 產生的 patch 會包含作者以及電子郵件,讓其他開發者更容易使用 (with `git am`) 以及給予回饋。 [IMPORTANT] **** 為了讓開發者更容易在他們的 ports tree 使用此 patch ,請基於你的 ports tree 來產生 [.filename]#.diff# 。 **** ==== 透過 https://bugs.freebsd.org/submit/[bug submission form] 繳交 [.filename]#oneko.diff# 。使用 "Ports & Packages" 產品和 "Individual Port(s)" 組件,然後跟著這裡的教學走,在 PR 的描述欄位 (也許是較短的 `COMMENT` ) 加入簡短的敘述,並且記得在附件中加入 [.filename]#oneko.diff# 。 [NOTE] ==== 在問題回報系統中給一個好的總結可以讓 port 開發者更輕鬆的處理此 port ,我們預期的描述形式為 "[NEW PORT] _category/portname short description of the port_" ,使用此形式能讓我們更快的部屬新的 port 。 ==== 送出 port 之後,請耐心等候佳音。 有時候可能需要等個幾天或幾個月時間,才會在 FreeBSD ports tree 上正式出現。 等待中的 port PR 清單可以在 http://www.FreeBSD.org/cgi/query-pr-summary.cgi?category=ports[] 查閱。 在搜尋表單中選擇 _Open_ and _Ports & Packages_ 來獲得 _open_ port PRs 的清單。 在看過新的 port 之後,如果需要的話,我們會回覆您,然後會將它提交到 port tree 。 您的大名會被列在 extref:{contributors}[Additional FreeBSD Contributors, contrib-additional] 列表上,以及其他檔案中。 也可以透過 man:shar[1] 檔案來提交 port ,請使用之前 `oneko` port 的例子。 .為新的 Port 創建 [.filename]#.shar# [[porting-submitting-shar]] [example] ==== 前往 port 所在的目錄,使用 `tar`創建 shar archive: [source,shell] .... % cd .. % tar cf oneko.shar --format shar oneko .... ==== 可以使用跟提交 [.filename]#oneko.diff# 一樣的方式來提交 [.filename]#oneko.shar# 。