您的位置:首页技术文章
文章详情页

对话 UNIX,第 12 部分: 自己动手完成项目

【字号: 日期:2024-06-18 09:48:28浏览:36作者:猪猪

Unix® 系统中提供了数百个实用工具应用程序或者命令。其中一些命令可以操作文件系统,而其他的命令则用于查询并控制操作系统本身。大量的命令提供了连接性,并且还有更丰富的命令可用于生成、交换、修改、筛选和分析数据。由于 UNIX 具有悠久而丰富的历史,所以您也许能够找到恰好合适的工具,以用于手头的任务。

此外,当一个实用工具不能满足需求时,您可以通过各种各样的方式结合任何数量的 UNIX 实用工具,以创建您自己的工具。正如您在前面的部分中所看到的,可以利用管道、重定向和条件,直接在命令行中构建即时可用的工具,并且 Shell 脚本将小型的、易于学习的编程语言的强大功能与 UNIX 命令结合在一起,以构建可重用工具。

当然,在很多情况下,仅依靠命令行和 Shell 脚本是不够的。例如,如果您必须部署一个新的守护进程以提供新的网络服务,那么您可以使用一种表达能力更强的语言,如 C 或者 Python,以便自己编写应用程序。并且,因为 Internet 上有许多应用程序是免费的(免费 意味着无需支付任何费用、得到自由条款的许可,或者两者都有),所以您还可以下载、编译并安装适当的、有效的解决方案,以满足您的需求。

UNIX(以及 Linux®)的许多版本都提供一种称为包管理器 的特殊工具,用以在系统中添加、删除和维护软件。包管理器通常可以维护本地安装的所有软件的详细目录,以及一个或者多个远程存储库 中所有可用软件的目录。您可以使用包管理器在存储库中搜索您所需要的软件。如果存储库中包含您正在寻找的软件,那么您只需要使用一个命令或者点击几下鼠标,就可以在您的系统中安装一个新的包。

包管理器是非常有价值的。使用它,您可以删除全部的包、更新现有的包,以及为任何包自动地检测并实现任何先决条件。例如,如果您选择了操作图像的软件,如可靠的 ImageMagick,但是您的系统中缺少处理 JPEG 图像的库,那么包管理器将在安装您所选择的包之前检测并安装缺少的内容。

然而,也可能存在这样的情况,即您所需要的软件是可获得的,但它却不包含于任何存储库中。由于包管理方式具有显著的优势,所以大多数软件都提供了可以使用包管理器进行下载并安装的形式。然而,因为 Unix 的版本和风格非常之多,所以很难针对每种特定的变体,以各种包管理器的格式提供每个应用程序。如果您的 UNIX 安装是主流的,并受到大量拥护者的喜爱,那么您将更有可能找到预先构建的并且可供使用的软件。否则,您就需要挽起袖子准备自己动手构建软件了。

是的,年轻的绝地武士(《星球大战》中的武士),是使用源代码的时候了。

如同从沼泽中升起一架 X 翼战斗机一样,从源代码构建软件乍看起来可能是令人生畏的,特别当您不是软件开发人员的时候。事实上,在大多数情况下,整个构建过程仅仅只需要少数几条命令,其余的工作都是自动完成的。

当然,某些程序构建起来是非常复杂的(或者需要花费数小时来进行构建),并且在构建过程中需要进行人工介入。然而,即使这些程序通常是由一些容易构建的较小的块构造而得到的,依赖关系的数量和构造的顺序也会使构建过程变得复杂。一些程序还有许多您并不一定希望拥有的特性。例如,您可以构建 PHP,以便与新的网际协议版本 6 (IPv6) Internet 寻址方案进行互操作。如果您的网络尚未采用 IPv6,则不需要包括这个特性。对大量选项进行的审查将使构建过程变得更加麻烦。

这个月,让我们来研究如何构建一个典型的 UNIX 软件应用程序。在继续学习后面的内容之前,请确保系统中安装了 C 编译器,如 GNU 编译器套装(GNU Compiler Collection,GCC),以及常见的 UNIX 软件开发工具套装,包括 make、m4、pkg-config 和 awk。此外,请确保在您的 PATH 环境变量中包含了所有的开发工具。

软件包中有价值的内容

作为一个说明性的和典型的示例,让我们配置、构建并安装 SQLite——一个实现结构化查询语言(Structured Query Language,SQL)数据库引擎的小型的库。SQLite 不需要进行任何配置即可使用,并且可以完整地嵌入到任何应用程序中,而数据库则包含在单个文件中。许多编程语言都可以调用 SQLite 以实现数据的持久化。SQLite 还包括一种用于管理 SQLite 数据库的、名为 sqlite3 的命令行实用工具。

要开始学习这部分内容,首先下载 SQLite(请参见参考资料)。选择最新的源代码包,并将其下载到您的计算机中。(在撰写本文时,SQLite 的最新版本是版本 3.3.17,于 2007 年4 月 25 日发布。)这个示例使用了 http://www.sqlite.org/sqlite-3.3.17.tar.gz 中存储的文件。

在您获得了该文件之后,请对其进行解压缩。.tar.gz 扩展反映了该存档文件是如何构造的。在这个示例中,它是一个压缩了的 tar 存档文件。后面的扩展 .gz,表示 gzip(压缩);前面的扩展 .tar,表示 tar(一种存档格式)。要提取该存档文件的内容,只需要对其进行反向处理即可,也就是首先解压缩,然后打开该存档文件:

$ gunzip sqlite-3.3.17.tar.gz$ tar xvf sqlite-3.3.17.tar

这两个命令在一个名为 sqlite-3.3.17 的新目录中创建了原始源代码的一个副本。顺便说明一下,.tar.gz 文件格式是非常常见的(称为 tarball),并且您可以使用 tar 命令直接解压缩 tarball 文件:

$ tar xzvf sqlite-3.3.17.tar.gz

这一个命令和前面的两个命令是等价的。

接下来,将目录更改为 sqlite-3.3.17,并使用 ls,以列出其中的内容。您应该看到与清单 1 所示类似的清单:

清单 1. SQLite 包的清单

$ lsMakefile.in contrib publish.shMakefile.Linux-gcc doc spec.templateREADME ext sqlite.pc.inVERSION install-sh sqlite3.1aclocal.m4 ltmain.sh  sqlite3.pc.inaddopcodes.awk main.mk srcart mkdll.shtclinstaller.tclconfig.guessmkopcodec.awk  testconfig.sub mkopcodeh.awk  toolconfigure  mkso.sh wwwconfigure.acnotes

其中的源代码和 SQLite 补充文件经过了很好组织,并且模拟了大部分的软件项目分发源代码的方式:

README 文件对该项目进行了描述,并且通常用于说明如何构建该软件。(README 文件还详细地介绍了使用条款,或者许可证、适用情况。许多项目的许可证代码都符合 GNU 公共许可版本 2 中的条款,即所谓的“copyleft许可证。在许可证与您打算如何使用该软件之间可能存在一定的冲突,如果您对此有任何疑问,最好请教一下合适的法律顾问。)

src 目录中包含了相关的代码。

test 目录中包含了一组测试,以验证该软件的操作是否正确。在开始构建或者进行了任何修改之后,请运行这些测试,这样可以增加对该软件的信心。

contrib 目录中包含核心 SQLite 开发团队所没有提供的附加软件。对于像 SQLite 这样的库,contrib 中可能包含一些常用语言(如 C、Perl、PHP 和 Python)的编程接口。它可能还包括图形用户界面(GUI)包装,以及更多的内容。

在其他文件中,Makefile.in、configure、configure.ac 和 aclocal.m4 用于生成在您的 Unix 版本中编译 SQLite 软件的脚本和规则。如果这个软件足够简单,那么要编译其代码,可能只需要一条简单的编译命令即可。但是,因为存在如此之多的 UNIX 变种(Mac OS X、Solaris、Linux、IBM® AIX® 和 HP/UX 等等),所以必须对宿主计算机进行分析,以确定它的功能及其实现。例如,邮件阅读应用程序可能会尝试确定本地系统是如何存储邮箱的,并包含对该格式的支持。

集中精力感受源代码

下一个步骤是探查系统并配置该软件,以便进行正确地构建。(您可以将这个步骤想象为裁剪一件衣服:这件衣服大小基本合适,但是需要进行一定的修改以使其更加时尚。)您需要进行自定义工作,并为使用 ./configure 本地脚本进行编译做好准备。在命令行提示处,键入:$ ./configure

这个配置脚本进行了几项测试,以证明您的系统是合格的。例如,在一台 Apple MacBook 计算机上(其中运行着 FreeBSD® UNIX 的一个变种)运行 ./configure,将产生以下结果(请参见清单 2):

清单 2. 在 Mac OS X 上运行 ./configure 的结果

checking build system type... i386-apple-darwin8.9.1checking host system type... i386-apple-darwin8.9.1checking for gcc... gccchecking for C compiler default output file name... a.outchecking whether the C compiler works... yeschecking whether we are cross compiling... nochecking for suffix of executables...checking for suffix of object files... ochecking whether we are using the GNU C compiler... yeschecking whether gcc accepts -g... yeschecking for gcc option to accept ISO C89... none neededchecking for a sed that does not truncate output... /usr/bin/sedchecking for grep that handles long lines and -e... /usr/bin/grepchecking for egrep... /usr/bin/grep -Echecking for ld used by gcc... /usr/bin/ld...

这里,./configure 可以确定编译和主机系统的类型(如果您采用交叉编译的话,它可能不同),证实是否已经安装了 GNU C 编译器(GCC),并找到其余构建过程可能需要使用的实用工具的路径。您可以浏览一下其余的输出,但是您将看到一个较长的诊断信息列表,该列表从成功构造 SQLite 的角度分析了您的系统的特点。

注意: ./configure 命令可能 会失败,特别是在无法找到一个先决条件的情况下(比如一个系统库或者关键的系统实用工具)。

浏览 ./configure 的输出,寻找其中不正常之处,如命令的专用或者本地版本,它可能并不适合于构建通用的应用程序,如 SQLite。作为一个示例,如果您的系统管理员安装了 GCC 的 alpha 版本,并且 configure 工具首选使用该版本,那么您可以选择手动地改写这个选择。要查看您可以改写的选项的列表(该列表通常很长),可以键入 ./configure --help,如清单 3 中所示:

清单 3. 用于 ./configure 脚本的通用选项

$ ./configure --help...By default, `make install' will install all the files in`/usr/local/bin', `/usr/local/lib' etc. You can specifyan installation prefix other than `/usr/local' using `--prefix',for instance `--prefix=$HOME'.For better control, use the options below.Fine tuning of the installation DirectorIEs: --bindir=DIR  user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR  program executables [EPREFIX/libexec]...

./configure --help 的输出中包括配置系统使用的通用选项,以及仅与您正在构建的软件相关的特定选项。要查看后者(较短)的列表,可以键入 ./configure --help=short(请参见清单 4):

清单 4. 要构建的软件包所特定的选项

$ ./configure --help=shortOptional Features: --disable-FEATURE  do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-shared[=PKGS] build shared librarIEs [default=yes] --enable-static[=PKGS] build static libraries [default=yes] --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --disable-libtool-lock avoid locking (might break parallel builds) --enable-threadsafe Support threadsafe operation --enable-cross-thread-connections Allow connection sharing across threads --enable-threads-override-locks Threads can override each others locks --enable-releasemodeSupport libtool link to release mode --enable-tempstore Use an in-ram database for temporary tables (never,no,yes,always) --disable-tcl  do not build TCL extension --disable-readline disable readline support [default=detect] --enable-debug enable debugging & verbose explain

返回到 ./configure --help,最顶部的输出显示了可执行文件的缺省安装目录是 /usr/local/bin,库文件的缺省安装目录是 /usr/local/lib,等等。许多系统使用一个替代的层次结构来存储非核心软件。

例如,许多系统管理员选择使用 /opt 而不是 /usr/local 存储本地添加的或者在本地进行了修改的软件。如果您希望将 SQLite 安装到与缺省目录不同的其他目录中,可以使用 --prefix= 选项指定该目录。一种可行的方法(也是一种常见的方法,如果只有您一个人使用这个软件包,或者如果您没有 root 访问权限以便在全局的范围内安装该软件)是将该软件安装到您的 home 目录中的层次结构中:$ ./configure --prefix=$HOME/sw

使用这个命令,构建过程的安装部分将在 $HOME/sw 中(比如 $HOME/sw/bin、$HOME/sw/lib、$HOME/sw/etc、$HOME/sw/man,以及其他所需的目录中)重新创建该软件的层次结构。为了简单起见,这个示例在缺省目标处安装其代码。

编译代码

./configure 的结果是一个与您的 Unix 版本兼容的 Makefile。名为 make 的开发实用工具将使用这个 Makefile,以执行编译所需的步骤,并将代码链接到一个可执行文件。您可以打开这个 Makefile 对其进行检查,但不要对它进行编辑,因为如果您再次运行 ./configure,它将列出您所做的任何修改。

这个 Makefile 中包含需要编译的源文件的列表,并且它还包括启用或者禁用并选择 SQLite 包中的某些代码片段的常数。例如,如果 configure 工具检测到了系统中合适的芯片,那么它可能会启用 64位处理器特定的代码。这个 Makefile 还说明了源文件之间的依赖关系,因此在一个非常重要的头文件 (.h) 中进行的一项更改,可能会导致重新编译所有的 C 源代码。

您的下一个步骤是运行 make,以构建该软件(请参见清单 5):

清单 5. 运行 make

$ makesed -e s/--VERS--/3.3.17/ ./src/sqlite.h.in | sed -e s/--VERSION-NUMBER--/3003017/ >sqlite3.hgcc -g -O2 -o lemon ./tool/lemon.ccp ./tool/lempar.c .cp ./src/parse.y ../lemon parse.ymv parse.h parse.h.tempawk -f ./addopcodes.awk parse.h.temp >parse.hcat parse.h ./src/vdbe.c | awk -f ./mkopcodeh.awk >opcodes.h./libtool --mode=compile --tag=CC gcc -g -O2 -I. -I./src -DNDEBUG -I/System/Lib rary/Frameworks/Tcl.framework/Versions/8.4/Headers -DTHREADSAFE=0 -DSQLITE_THREA D_OVERRIDE_LOCK=-1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -c ./src/alter.cmkdir .libsgcc -g -O2 -I. -I./src -DNDEBUG -I/System/Library/Frameworks/Tcl.framework/Vers ions/8.4/Headers -DTHREADSAFE=0 -DSQLITE_THREAD_OVERRIDE_LOCK=-1 -DSQLITE_OMIT_L OAD_EXTENSION=1 -c ./src/alter.c -fno-common -DPIC -o .libs/alter.o...ranlib .libs/libtclsqlite3.acreating libtclsqlite3.la

注意: 在上面的输出中,添加了一些空白行,以便更好地突出显示 make 发起的每个步骤。

make 实用工具检查文件(头文件、源代码、数据文件和目标文件)的修改日期,并编译合适的 C 源文件。最初,make 将重新编译所有内容,因为不存在任何目标文件或者编译目标。正如您可以看到的,用于编译目标的规则还包括一些中间步骤,其中使用了一些相关的工具,如 sed 和 awk,以产生在后续的步骤中将要使用的头文件。

执行 make 命令所得到的结果是一个完成的库和 sqlite3 实用工具。

最好对您刚编译的软件进行测试,尽管这在每个包中并不是强制的,也没有提供相应的内容。即便成功地构建 了您的软件,也不一定就表示该软件能够正确地运行。

要测试您的软件,可以再次运行 make,并使用 test 选项(请参见清单 6):

清单 6. 对软件进行测试

$ make test...alter-1.1... Okalter-1.2... Okalter-1.3... Okalter-1.3.1... Okalter-1.4... Ok...Thread-specific data deallocated properly0 errors out of 28093 testsFailures on these tests:

成功了!该软件构建成功,并且工作正常。如果其中一个或者多个测试用例失败了,那么底部的总结(这里,它是空白的)将向您报告哪一项测试或者哪几项测试需要进一步研究。

完成后的产品

如果您的软件工作正常,那么最后一个步骤是将它安装到您的系统中。同样,使用 make,并指定 install 目标。要将软件添加到 /usr/local,通常需要由 sudo 所提供的超级用户(root)权限(请参见清单 7):

清单 7. 在您的本地系统中安装软件

$ sudo make installtclsh ./tclinstaller.tcl 3.3/usr/bin/install -c -d /usr/local/lib./libtool --mode=install /usr/bin/install-c libsqlite3.la /usr/local/lib /usr/bin/install-c .libs/libsqlite3.0.8.6.dylib /usr/local/lib/libsqlite3.0.8.6 .dylib.../usr/bin/install -c .libs/libsqlite3.lai /usr/local/lib/libsqlite3.la/usr/bin/install -c .libs/libsqlite3.a /usr/local/lib/libsqlite3.achmod 644 /usr/local/lib/libsqlite3.aranlib /usr/local/lib/libsqlite3.a.../usr/bin/install -c -d /usr/local/bin./libtool --mode=install /usr/bin/install -c sqlite3 /usr/local/bin/usr/bin/install -c .libs/sqlite3 /usr/local/bin/sqlite3/usr/bin/install -c -d /usr/local/include/usr/bin/install -c -m 0644 sqlite3.h /usr/local/include/usr/bin/install -c -m 0644 ./src/sqlite3ext.h /usr/local/include/usr/bin/install -c -d /usr/local/lib/pkgconfig;/usr/bin/install -c -m 0644 sqlite3.pc /usr/local/lib/pkgconfig;

标签: Unix系统
相关文章: