Ports & Package

在 Windows 底下要安装新的应用程式时 , 通常就是执行一下 SETUP.EXE
, 选选安装目录 , 回答几个简单问题 , 然後 SETUP.EXE 就会帮你把该做
的事做好 。但是在 UN*X 的世界里通常不是就不是这麽简单了 , 除非你
买的是商业软体 , 不然一般你拿到的会是一包一包的 source code , 而
不是现成弄好的可执行档 。

在 Windows 的世界里 , 一方面因为应用程式是一个个的商品 , 为了商品
的利益 , 厂商不可能把形同命脉的 source code 丢出来给你;另一方面
也因为 Windows 就只在 Intel 系列的平台上面执行(当做没有 NT 可
以在 Alpha 上面跑这一回事存在 :P ) , 它就不需要考虑编成 binary
後在不同平台上面的适应性 。反观 UN*X 的世界 , UN*X 是架构在各式各
样不同的平台上面 , 你绝对没办法用同一套 binary 吃遍所有的系统 。
而且在 UN*X 世界中 , 许多程式的作者并不把能从他写的程式获得多少
利益摆在最重要的位置 , 而是希望他所写的程式能让更多的人受惠 , 并
希望他的程式能变好 , 所以他们会把 source code 放出来 , 大家一
起来集思广益 , 让程式更好 。

在 UN*X 下的程式 , 一般都是用 C 语言来写的 。虽然 C 语言有它的标
准 , 而且本身已经有很好的可携性 , 但是在不同的 UN*X 系统下 , 却还
是会有 "大同小异" 的问题存在 。虽然整个程式的大体架构、语法大致
相同 , 但是不同的系统间还是有些小小的差异 , 比如说 head file 的不
同啦、资料型态资料大小的不同啦、系统目录结构的不同啦....etc 。因
为这些大同小异 , 所以即使你在一个系统上面写的程式能在这个系统上
面正常的 compile , 正确的执行 , 但是拿到另一个系统上面却未必行得
通 , 通常必需视不同的系统做不同的修改 。这种把 A 系统上面可以正常
运作的程式 , 弄成在 B 系统上面也能正常运作的工作 , 就称为 "PORT"


简单的 PORT 可能改改目录位置 , 加上几个 #ifdef 之类的东东就可以
解决了 , 但是有时候如果遇到像是程式和系统的关连太深、程式用到一
些 A 系统内部提供但 B 系统却没有的功能时 , 那 PORT 的工作就不是
那麽简单了 。但是 , 如果你选用了 FreeBSD , 那就只有一句话:啊~福
气啦!在 FreeBSD coreteam 有系统的整理之下 , 目前 FreeBSD 已经有
超过二千种各式各样应用程式的 ports , 使用这些 ports , 你不需要自
己再去看 source 改 code , 所有需要修改的部份都已经有人代劳 , 帮你
改得好好的 , 你所需要做的事情非常的简单:make install 。是的 , 就
是这麽一道指令 , 一切 OK 。

因为目前 FreeBSD 只能在 Intel 系列的系统上跑 , 所以如果你觉得用
ports 还要自己 compile 很麻烦 , FreeBSD 提供你另一项选择:package
。所谓的 package 就是有人帮你把程式都 compile 成 binary 了 , 并
把这些 binary 及一些相关的文件、档案压成一个 *.tgz 档 , 你只需要
直接用 pkg_add 就可以进行安装 , 把这些 binary 放进系统里面 , 直接
就可以使用了 , 方便省事 。不过一般如果可以的话还是比较建议使用
ports 来安装 。

package 就是别人帮你 compile 好的 ports , 而 ports 就是要自己从
source code 来 compile 出 binary , 但是已经有人把该修改的东东修
改好了 , 你无需再烦心如何让这个程式能在 FreeBSD 上正常的 compile
正常的运作 。一般的 ports/package 都会把东东放到 /usr/local 目录
下面 , 执行档就放到 /usr/local/bin , 设定资料放在 /usr/local/etc
, library 放在 /usr/local/lib , manual 放在 /usr/local/man 。

package 是一个一个的 tgz 档 , 你可以在
ftp://freebsd.csIE.nctu.edu.tw/pub/packages-* 目录下面找到所有
的 package , 如果你用的是 FreeBSD 2.2* , 就找 packages-2.2 , 若是
3.0* , 则是 packages-3.0 。packages-* 目录下面还把各种 packages
依照功能等特性分类 , 让你可以更方便的找到你所要的东东 。在这里就
拿 audio/amp-0.7.6.tgz 来说 , 用 tar -tvzf amp-0.7.6.tgz 可以看
到它的内容如下:

-rw-r--r-- root/bin 181 Nov 6 17:54 1997CONTENTS
-rw-r--r-- root/bin 19 Nov 6 17:54 1997COMMENT
-rw-r--r-- root/bin 514 Nov 6 17:54 1997DESC
-rw-r--r-- root/wheel 4358 Nov 6 09:14 1997MTREE_DIRS
-r-xr-xr-x bin/bin 94208 Nov 6 17:53 1997 bin/amp
-r--r--r-- bin/bin 853 Nov 6 17:53 1997 man/man1/amp.1.gz

其中COMMENT 这个档案简单介绍一下这个 package , 而DESC 里面则
是较详细的介绍或是一些注意事项等 。CONTENTS 里面则是列出了这个
package 里面有哪些档案 , 它们会被安装到哪里去 。你用 pkg_add 来安
装或是用 pkg_delete 来反安装 package 时会参考到这些资料 。
MTREE_DIRS 里面放的是要丢给 mtree 的资料 , 用来设定档案目录的权
限等等的 。接下来有几个目录、档案 。这些目录都是相对於 /usr/local
的 , 也就是说这里面的 bin/amp 到时候会安装到 /usr/local/bin/amp
之下 。和 package 相关的几个指令详述如下:

pkg_info:用来查看这个 package 是什麽 。它会把 package 里面的
COMMENT 和DESC 抓出来 , 解说一下这个 package 的功能等资料 。

pkg_add:用来安装 package 。它会按照 package 里面的设定 , 把各个
档案拷到正确的位置 , 然後在 /var/db/pkg 下面造出该 package 的目
录 , 把CONTENTSCOMMENTDESC 等档案拷过去 。以前面的 amp 来说
, 使用 pkg_add amp-0.7.6.tgz 会建立并把这三个档案拷到
/var/db/pkg/amp-0.7.6 目录下去 。

pkg_delete:用来反安装 package 。它会到 /var/db/pkg/[package] 目
录下面找出这个 package 安装了哪些东东 , 把它们通通移除 , 最後会把
/var/db/pkg/[package] 目录也移除 。比如说要反安装前面安装过的
amp , 直接执行 pkg_delete amp-0.7.6 即可 。

如果你凡事都喜欢自己来事必亲躬 , 那麽你可以自己从 ports 里面做
compile , 如果你看得懂 source , 还可以自己改改 code , 做做 tuning
, 量身订做弄出一个最适合自己的专用程式来 。这种一手掌控的快感 ,
是你用 Windows 系统时所无法享受到的 。ports 主要分为两部份 , 一部
份就是原始的 source code , 这些 source 大部份都放在
ftp://freebsd.csie.nctu.edu.tw/pub/distfiles 里面 。另一部份则是
这个 ports 如果要在 FreeBSD 下面编译、执行的话所需要的修改及摆
放的位置等设定 , 这一部份主要是放在
ftp://freebsd.csie.nctu.edu.tw/pub/ports-* 目录下面 。这个目录和
package 一样 , 也是依照不同的应用特性来做分类 。还是拿 amp 来说 ,
在 audio/amp 目录下面 , 你可以看到:

drwxr-xr-x 2 UPLOAD UPLOAD 512 Oct 9 00:24 CVS
-rw-r--r-- 1 UPLOAD UPLOAD 528 Sep 3 08:35 Makefile
drwxr-xr-x 3 UPLOAD UPLOAD 512 Oct 9 00:24 files
drwxr-xr-x 3 UPLOAD UPLOAD 512 Oct 9 00:24 patches
drwxr-xr-x 3 UPLOAD UPLOAD 512 Oct 9 00:24 pkg

Makefile 指定了这个 ports 该如何编译、source code 要去哪里抓、
需要先安装哪些其它相关的 ports、如何 instal.... 等等的讯息 。
files 目录下一般是放 source code 的 md5 checksum , 以免抓到错误
的 source code 包裹 。patches 里面放的是这个 ports 如果要改用到
FreeBSD 下面所需要做的修改 。pkg 目录下面是这个 ports 的相关资料
, 和 package 里面那些CONTENTSCOMMENTDESC 有相同的功效 。如
果你要使用 ports , 必需把该目录下的所有东东(嗯 , 其实 CVS 都没用
到)照原来的目录结构整个抓下来 , 如果你是用 ncftp , 就用 get -R
来抓 。一般抓下来的 ports 应该是放在 /usr/ports/ 下的对应目录下
, 如 amp 就应该放在 /usr/ports/audio/amp/ 下 , 但是并没有硬性规
定就是了 。

整个目录抓下来後 , 再来就是要执行 make 了 。在 ports 下 make 有几
种不同的参数 , 这些参数在 /usr/share/mk/bsd.port.mk 里面都有详细
的解说 。当你直接打 make 时 , 其实就是按照 fetch(抓回 source) ->
extract(检查 source 的 md5 并解开 source) -> patch(对 source 做
patch) -> configure(设定) -> build(编译) 这样一路做下来 , 把整个
ports 编译好 , 而要等到你指定了 make install 後才会真的把这个
ports 安装到系统上去 。最後安装完後可以再 make clean , 把解开的
source 等东东清除掉 。

在 make fetch 时 , 系统会依照下列顺序来寻找需要的 source:

1. /usr/ports/distfiles 下
2. /etc/make.conf 档中指定的 MASTER_SITE_BACKUP
3. Makefile 里指定的 MASTER_SITES

/etc/make.conf 内定是到 FreeBSD 总部去抓 , 不过其实一般这些
source 都可以在 ftp://freebsd.csie.nctu.edu.tw/pub/distfiles 目
录下面抓到 , 所以你可以把 MASTER_SITE_BACKUP 改成:

MASTER_SITE_BACKUP?=
ftp://freebsd.csie.nctu.edu.tw/pub/distfiles/${DIST_SUBDIR}/

节省到国外抓档的频宽 。当 make extract 後 , 会把 source 解开到
working 目录下去 。如果你想自己改一改 source , 可以在 make patch
之後到 working 目录下去修改 。然後 make configure 和 make build
时我们大概也没什麽事好做了 , 就看电脑萤幕上的字一行行的向上 ,
简单一点的 ports 可能你做十下伏地挺身它就能 make 好 , 大一点的可
能就你出去跟人聊天串门子回来後它还在跑 。

有时候呢 , ports A 会和 ports B 发生关 , 在安装 ports A 时系统
会去找 ports B , 如果找到会先装好 ports B 再回头来装 ports A , 但
是如果找不到 ports B 时就会给你一个警告 , 你就需要再去抓 ports B
回来安装 。但是这样缺啥补啥也是满麻烦的 , 即然用了 FreeBSD 就要善
用 FreeBSD 提供的好用功能 -- CTM 。首先 , /usr/ports 下最好有
50Mb 左右的硬碟空间 , 然後到
ftp://freebsd.csie.nctu.edu.tw/pub/CTM/ports-cur 下面抓回
ports-cur.????xEmpty.gz(找一个数字最大的 ???? 抓)以及所有
* > ???? 的 ports-cur.*.gz , 比如说你抓了 ports-cur.2000xEmpty.gz
, 那就要把 ports-cur.2001.gz, ports-cur.2002.gz.... 通通抓回来
。如果你抓回来的 gz 档都放在 /tmp/ctm 下 , 就使用以下指令:

cd /usr/ports
/bin/rm -rf *
ctm -v /tmp/ctm/*

这样就会把全部的 ports 通通收在你的系统上 , 以後安装时就不需要再
担心缺东少西的问题了 。而且之後如果 ports 又有更新 , 也只需要抓回
新的 gz 档 , 用 ctm 来更新即可 , 方便又省事 。