邪恶八进制信息安全团队技术讨论组's Archiver

pub!1c 2006-5-7 22:06

[转载]使用Automake生成Makefile

<p>信息来源:ChinaUnix</p><p>Makefile <br /><br />在 Unix 上写程式的人大概都碰过 Makefile,尤其是用 C 来开发程式的 <br />人。用 make 来开发和编译程式的确很方便,可是要写出一个 Makefile <br />就不简单了。偏偏介绍 Makefile 的文件不多,GNU Make 那份印出来要几 <br />百页的文件,光看完 Overview 就快阵亡了,难怪许多人闻 Unix 色变。 <br />本文将介绍如何利用 GNU Autoconf 及 Automake 这两套软体来协助我们 <br />『自动』产生 Makefile 档,并且让开发出来的软体可以像 Apache, <br />MySQL 和常见的 GNU 软体一样,只要会 ``./configure'', ``make'', <br />``make install'' 就可以把程式安装到系统中。如果您有心开发 Open <br />Source 的软体,或只是想在 Unix 系统下写写程式。希望这份介绍文件能 <br />帮助您轻松地进入 Unix Programming 的殿堂。 <br /><br />1. 简介 <br />Makefile 基本上就是『目标』(target), 『关连』(dependencies) 和 <br />『动作』三者所组成的一连串规则。而 make 就会根据 Makefile 的规则 <br />来决定如何编译 (compile) 和连结 (link) 程式。实际上,make 可做的 <br />不只是编译和连结程式,例如 FreeBSD 的 port collection 中, <br />Makefile 还可以做到自动下载原始程式套件,解压缩 (extract) ,修补 <br />(patch),设定,然後编译,安装至系统中。 <br /><br />Makefile 基本构造虽然简单,但是妥善运用这些规则就也可以变出许多不 <br />同的花招。却也因此,许多刚开始学习写 Makefile 时会感到没有规范可 <br />循,每个人写出来的 Makefile 长得都不太一样,不知道从何下手,而且 <br />常常会受限於自己的开发环境,只要环境变数不同或路径改一下,可能 <br />Makefile 就得跟着修改。虽然有 GNU Makefile Conventions (GNU <br />Makefile 惯例) 订出一些使用 GNU 程式设计时撰写 Makefile 的一些标 <br />准和规范,但是内容很长而且很复杂, 并且经常做些调整,为了减轻程式 <br />设计师维护 Makefile 的负担,因此有了 Automake。 <br /><br />程式设计师只需写一些预先定义好的巨集 (macro),交给 Automake 处理 <br />後会产生一个可供 Autoconf 使用的 Makefile.in 档。再配合利用 <br />Autoconf 产生的自动设定档 configure 即可产生一份符合 GNU Makefile <br />惯例的 Makeifle 了。 <br /><br />2. 上路之前 <br /><br />在开始试着用 Automake 之前,请先确认你的系统已经安装以下的软体: <br /><br />1. GNU Automake <br />2. GNU Autoconf <br />3. GNU m4 <br />4. perl <br /><br />5. GNU Libtool (如果你需要产生 shared library) <br /><br />我会建议你最好也使用 GNU C/C++ 编译器 、GNU Make 以及其它 GNU 的 <br />工具程式来做为开发的环境,这些工具都是属於 Open Source Software <br />不仅免费而且功能强大。如果你是使用 Red Hat Linux 可以找到所有上述 <br />软体的 rpm 档,FreeBSD 也有现成的 package 可以直接安装,或着你也 <br />可以自行下载这些软体的原始档回来 DIY。以下的范例是在 Red Hat <br />Linux 5.2 + CLE2 的环境下所完成的。 <br /><br /><br />3. 一个简单的例子 <br /><br />Automake 所产生的 Makefile 除了可以做到程式的编译和连结,也已经把 <br />如何产生程式文件 (如 manual page, info 档及 dvi 档) 的动作,还有 <br />把原始程式包装起来以供散 的动作都考虑进去了,所以原始程式所存放 <br />的目录架构最好符合 GNU 的标准惯例,接下来我拿 hello.c 来做为例 <br />子。 <br /><br />在工作目录下建立一个新的子目录 ``devel'',再在 devel 下建立一个 <br />``hello'' 的子目录,这个目录将作为我们存放 hello 这个程式及其相关 <br />档案的地方: <br /><br />% mkdir devel <br /><br />% cd devel <br /><br />% mkdir hello <br /><br />% cd hello <br /><br />用编辑器写个 hello.c 档, <br /><br />#include <br /><br />int main(int argc, char** argv) <br />{ <br />printf(``Hello, GNU!\n''); <br />return 0; <br />} <br /><br />接下来就要用 Autoconf 及 Automake 来帮我们产生 Makefile 档了, <br /><br />1. 用 autoscan 产生一个 configure.in 的雏型,执行 autoscan 後会产 <br />生一个configure.scan 的档案,我们可以用它做为 configure.in <br />档的蓝本。 <br />% autoscan <br />% ls <br />configure.scan hello.c <br />2. 编辑 configure.scan 档,如下所示,并且把它的档名改成 <br />configure.in <br />dnl Process this file with autoconf to produce a con <br />figure script. <br />AC_INIT(hello.c) <br />AM_INIT_AUTOMAKE(hello, 1.0) <br />dnl Checks for programs. <br />AC_PROG_CC <br />dnl Checks for libraries. <br />dnl Checks for header files. <br />dnl Checks for typedefs, structures, and compiler ch <br />aracteristics. <br />dnl Checks for library functions. <br />AC_OUTPUT(Makefile) <br /><br />3. 执行 aclocal 和 autoconf ,分别会产生 aclocal.m4 及 configure 两个档案 <br />% aclocal <br />% autoconf <br />% ls <br />aclocal.m4 configure configure.in hello.c <br /><br />4. 编辑 Makefile.am 档,内容如下 <br />AUTOMAKE_OPTIONS= foreign <br />bin_PROGRAMS= hello <br />hello_SOURCES= hello.c <br /><br />5. 执行 automake --add-missing ,Automake 会根据 Makefile.am 档产生 <br />一些档案,包含最重要的 Makefile.in <br />% automake --add-missing <br />automake: configure.in: installing `./install-sh' <br />automake: configure.in: installing `./mkinstalldirs' <br />automake: configure.in: installing `./missing' <br /><br />6. 最後执行 ./configure , <br />% ./configure <br />creating cache ./config.cache <br />checking for a BSD compatible install... /usr/bin/in <br />stall -c <br />checking whether build environment is sane... yes <br />checking whether make sets ${MAKE}... yes <br />checking for working aclocal... found <br />checking for working autoconf... found <br />checking for working automake... found <br />checking for working autoheader... found <br />checking for working makeinfo... found <br />checking for gcc... gcc <br />checking whether the C compiler (gcc ) works... yes <br />checking whether the C compiler (gcc ) is a cross-co <br />mpiler... no <br />checking whether we are using GNU C... yes <br />checking whether gcc accepts -g... yes <br />updating cache ./config.cache <br />creating ./config.status <br />creating Makefile <br />现在你的目录下已经产生了一个 Makefile 档,下个 ``make'' 指令就可 <br />以开始编译 hello.c 成执行档,执行 ./hello 和 GNU 打声招呼吧! <br />% make <br />gcc -DPACKAGE=\"hello\" -DVERSION=\"1.0\" -I. -I. -g -O2 -c he <br />llo.c <br />gcc -g -O2 -o hello hello.o <br />% ./hello <br />Hello! GNU! <br />你还可以试试 ``make clean'',''make install'',''make dist'' 看看 <br />会有什麽结果。你也可以把产生出来的 Makefile 秀给你的老板,让他从 <br />此对你刮目相看 <br /><br />4. 一探究竟 <br />上述产生 Makefile 的过程和以往自行编写的方式非常不一样,舍弃传统 <br />自行定义 make 的规则,使用 Automake 只需用到一些已经定义好的巨集 <br />即可。我们把巨集及目标 (target) 写在 Makefile.am 档内,Automake <br />读入 Makefile.am 档後会把这一串已经定义好的巨集展开并且产生对应的 <br />Makefile.in 档, 然後再由 configure 这个 shell script 根据 <br />Makefile.in 产生适合的 Makefile。 <br /><br />[Figure 1:利用 autoconf 及 automake 产生 Makefile 的流程] <br />上图中表示在上一节范例中所要用的档案以及产生出来的档案,有星号 <br />(*) 者代表可执行档。在此范例中可藉由 Autoconf 及 Automake 工具所 <br />产生的档案有 configure.scan、aclocal.m4、configure、Makefile.in, <br />需要我们加入设定者为 configure.in 及 Makefile.am。 <br /><br />4.1 编辑 configure.in 档 <br />Autoconf 是用来产生 'configure' 档的工具。'configure' 是一个 <br />shell script,它可以自动设定原始程式以符合各种不同平台上 Unix 系 <br />统的特性,并且根据系统叁数及环境产生合适的 Makefile 档或是C 的标 <br />头档 (header file),让原始程式可以很方便地在这些不同的平台上被编 <br />译出来。Autoconf 会读取 configure.in 档然後产生 'configure' 这个 shell script。 <br />configure.in 档的内容是一连串 GNU m4 的巨集,这些巨集经过 <br />autoconf 处理後会变成检查系统特徵的 shell script。configure.in 内 <br />巨集的顺序并没有特别的规定,但是每一个 configure.in 档必须在所有 <br />巨集前加入 AC_INIT 巨集,然後在所有巨集的最後面加上 AC_OUTPUT 巨 <br />集。我们可先用 autoscan 扫描原始档以产生一个 configure.scan 档, <br />再对 configure.scan 做些修改成 configure.in 档。在范例中所用到的 <br />巨集如下: <br />dnl 这个巨集後面的字不会被处理,可视为注解。 <br />AC_INIT(FILE) 这个巨集用来检查原始码所在的路径,autoscan 会自动产生,我们不必修改它。 <br />AM_INIT_AUTOMAKE(PACKAGE,VERSION)这是使用 Automake 所必备的巨集,PACKAGE 是我们所要产生软体套件的名称,VERSION 是版本编号。 <br />AC_PROG_CC 检查系统可用的 C 编译器,如果原始程式是用 C 写的就需要这个巨 集。 <br />AC_OUTPUT(FILE) 设定 configure 所要产生的档案,如果是 Makefile 的话, configure 便会把它检查出来的结果带入 Makefile.in 档然後产生合适的 Makefile。 <br />实际上,我们使用 Automake 时,还须要一些其它的巨集,这些额外的巨集我们用 aclocal 来帮我们产生。执行 aclocal 会产生 aclocal.m4 档,如果没有特别的用途,我们可以不必修改它,用 aclocal 所产生的巨集会告诉 Automake 怎麽做。 有了 configure.in 及 aclocal.m4 两个档案後,便可以执行 autoconf 来产生 configure 档了。 <br />4.2 编辑 Makefile.am 档 <br />接下来我们要编辑 Makefile.am 档,Automake 会根据 configure.in 中 的巨集把Makefile.am 转成 Makefile.in 档。Makefile.am 档定义我们所 要产的目标: <br />AUTOMAKE_OPTIONS 设定 automake 的选项。Automake 主要是帮助开发 GNU 软体 <br />的人员维护软体套件,所以在执行 automake 时,会检查目录下是否存在标 准 GNU 软体套 <br />件中应具备的文件档案,例如 'NEWS'、'AUTHOR'、'ChangeLog' 等文件档。设成 foreign 时,automake 会改用一般软体套件的标准来检查。 <br />bin_PROGRAMS 定义我们所要产生的执行档档名。如果要产生多个执行档,每个档名用空白字元隔开。 <br />hello_SOURCES定义 'hello' 这个执行档所需要的原始档。如果 'hello' 这个程式是由多个原始档所产生,必须把它所用到的原始档都列出来,以空白 <br /><br />字元隔开。假设 'hello' 这个程式需要 'hello.c'、'main.c'、 <br /><br />'hello.h' 三个档案的话,则定义 <br /><br /><br />hello_SOURCES= hello.c main.c hello.h <br /><br />如果我们定义多个执行档,则对每个执行档都要定义相对的 <br /><br />filename_SOURCES。 <br /><br /><br />编辑好 Makefile.am 档,就可以用 automake --add-missing 来产生 <br /><br />Makefile.in。加上 --add-missing 选项是告诉 automake 顺便帮我们加 <br /><br />入包装一个软体套件所必备的档案。Automake 产生出来的 Makefile.in <br /><br />档是完全符合 GNU Makefile 的惯例,我们只要执行 configure 这个 <br /><br />shell script 便可以产生合适的 Makefile 档了。 <br /><br /><br />4.3 使用 Makefile <br /><br /><br />利用 configure 所产生的 Makefile 档有几个预设的目标可供使用,我们 <br /><br />只拿其中几个简述如下: <br /><br /><br />make all <br /><br />产生我们设定的目标,即此范例中的执行档。只打 make 也可以,此 <br /><br />时会开始编译原始码,然後连结,并且产生执行档。 <br /><br />make clean <br /><br />清除之前所编译的执行档及目的档 (object file, *.o)。 <br /><br />make distclean <br /><br />除了清除执行档和目的档外,也把 configure 所产生的 Makefile <br /><br />也清除掉。 <br /><br />make install <br /><br />将程式安装至系统中。如果原始码编译无误,且执行结果正确,便可 <br /><br />以把程式安装至系统预设的执行档存放路径。如果我们用 <br /><br />bin_PROGRAMS 巨集的话,程式会被安装至 /usr/local/bin 这个目 <br /><br />录。 <br /><br />make dist <br /><br />将程式和相关的档案包装成一个压缩档以供散播 (distribution) 。 <br /><br />执行完在目录下会产生一个以 PACKAGE-VERSION.tar.gz 为名称的档 <br /><br />案。PACKAGE 和 VERSION 这两个变数是根据 configure.in 档中 <br /><br />AM_INIT_AUTOMAKE(PACKAGE, VERSION) 的定义。在此范例中会产生 <br /><br />'hello-1.0.tar.gz' 的档案。 <br /><br />make distcheck <br /><br />和 make dist 类似,但是加入检查包装後的压缩档是否正常。这个 <br /><br />目标除了把程式和相关档案包装成 tar.gz 档外,还会自动把这个压 <br /><br />缩档解开,执行 configure,并且进行 make all 的动作,确认编译 <br /><br />无误後,会显示这个 tar.gz 档已经准备好可供散播了。这个检查非 <br /><br />常有用,检查过关的套件,基本上可以给任何一个具备 GNU 发展环 <br /><br />境的人去重新编译。就 hello-1.tar.gz 这个范例而言,除了在 Red <br /><br />Hat Linux 上,在 FreeBSD 2.2.x 版也可以正确地重新编译。 <br /><br /><br />要注意的是,利用 Autoconf 及 Automake 所产生出来的软体套件是可以 <br /><br />在没有安装 Autoconf 及 Automake 的环境上使用的,因为 configure 是 <br /><br />一个 shell script,它己被设计可以在一般 Unix 的 sh 这个 shell 下 <br /><br />执行。但是如果要修改 configure.in 及 Makefile.am 档再产生新的 <br /><br />configure 及 Makefile.in 档时就一定要有 Autoconf 及 Automake 了。 <br /><br /><br />5. 相关讯息 <br /><br /><br />Autoconf 和 Automake 功能十分强大,你可以从它们所附的 info 档找到 <br /><br />详细的用法。你也可以从许多现存的 GNU 软体或 Open Source 软体中找 <br /><br />到相关的 configure.in 或 Makefile.am 档,它们是学习 Autoconf 及 <br /><br />Automake 更多技巧的最佳范例。 <br /><br /><br />这篇简介只用到了 Autoconf 及 Automake 的皮毛罢了,如果你有心加入 <br /><br />Open Source 软体开发的行列,希望这篇文件能帮助你对产生 Makefile <br /><br />有个简单的依据。其它有关开发 GNU 程式或 C 程式设计及 Makefile 的 <br /><br />详细运用及技巧,我建议你从 GNU Coding Standards3 (GNU 编码标准规 <br /><br />定) 读起,里面包含了 GNU Makefile 惯例,还有发展 GNU 软体套件的标 <br /><br />准程序和惯例。这些 GNU 软体的线上说明文件可以在 <br /><br />[url]http://www.gnu.org/[/url] 这个网站上找到。 <br /><br /><br />6. 结语 <br /><br /><br />经由 Autoconf 及 Automake 的辅助,产生一个 Makefile 似乎不再像以 <br /><br />前那麽困难了,而使用 Autoconf 也使得我们在不同平台上或各家 Unix <br /><br />之间散播及编译程式变得简单,这对於在 Unix 系统上开发程式的人员来 <br /><br />说减轻了许多负担。妥善运用这些 GNU 的工具软体,可以帮助我们更容易 <br /><br />去发展程式,而且更容易维护原始程式码。 <br /><br /><br />一九九八年是 Open Source 运动风起云涌的一年,许多 Open Source 的 <br /><br />软体普遍受到网路上大众的欢迎和使用。感谢所有为 Open Source 奉献的 <br /><br />人们,也希望藉由本文能吸引更多的人加入『自由』、『开放』的 Open <br /><br />Source 行列。 <br /><br /><br />About this document ... <br /><br /><br />轻轻松松产生 Makefile1 <br /><br /><br />This document was generated using the LaTeX2HTML translator <br /><br />Version 98.2 beta6 (August 14th, 1998) <br /><br /><br />Copyright (C) 1993, 1994, 1995, 1996, Nikos Drakos, Computer <br /><br />Based Learning Unit, University of Leeds. <br /><br />Copyright (C) 1997, 1998, Ross Moore, Mathematics Department, <br /><br />Macquarie University, Sydney. <br /><br /><br />The command line arguments were: <br /><br />latex2html -split 0 -show_section_numbers automake.tex <br /><br /><br />The translation was initiated by on 1999-02-11 <br /><br /><br /><br />Footnotes <br /><br /><br />...\title1 <br /><br />本文件使用 ChiLaTeX 制作。 <br /><br />... CLE2 <br /><br />CLE (Chinese Linux Extension,Linux 中文延伸套件), <br /><br />[url]http://cle.linux.org.tw/[/url] <br /><br />... Standards3 <br /><br />GNU Coding Standards, Richard Stallman.<!-- / message --></p>

页: [1]
© 1999-2008 EvilOctal Security Team