作为Linux下的程序开发者,一定遇到过Makefile。使用make命令编译自己的程序真的很方便。一般情况下,大家手写一个简单的Makefile。编写符合自由软件约定的Makefile并不是那么容易。在这篇文章中,我们将介绍如何使用autoconf和automake这两个工具来帮我们自动生成一个符合自由软件约定的Makefile,这样你就可以像普通的GNU程序一样将程序安装到Linux系统中,只需使用“./configure”、“make”和“makeinstall”。这将特别适合想要做开源软件的程序开发者,或者如果你只是自己写一些小Toy程序,那么这篇文章也会对你有很大的帮助。一、Makefile介绍Makefile用于自动编译和链接。一个项目由许多文件组成。每个文件的更改都会导致项目重新链接,但并非所有文件都需要重新编译。Makefile中记录了文件的信息,链接时需要重新编译哪些文件将在make中确定。Makefile的目的是让编译器知道它依赖于哪些其他文件来编译一个文件。当那些依赖文件发生变化时,编译器会自动发现最终生成的文件已经过时,并重新编译相应的模块。Makefile的基本结构并不是很复杂,但是程序开发人员在开始编写Makefile时,常常会怀疑自己写的是否符合约定,而自己编写的Makefile往往与自己的开发环境相关联。当系统环境变量或路径发生改变后,Makefile可能要进行相应的修改。这就造成了很多手工编写Makefile的问题,而automake可以很好的帮助我们解决这些问题。使用automake,程序开发人员只需要编写一些包含预定义宏的简单文件,autoconf根据一个宏文??件生成configure,automake根据另一个宏文件生成Makefile.in,然后使用configure生成一个Makefile.in常规Makefile。下面我们将详细介绍Makefile的automake生成方法。2、使用的环境本文提到的程序是基于Linux发行版:Linux2.6.18-194.el5,其中包含了我们需要使用的autoconf和automake。如果没有,您可以自己下载autoconf和automake。3.从helloworld开始我们从最常用的示例程序helloworld开始。下面的过程很简单:创建三个文件: helloworld.c configure.in Makefile.am然后执行:autoscan;本地的;自动配置;automake——添加缺失;./配置;制作;。/你好世界;可以看到生成了Makefile,可以编译helloworld.c了。很简单,几个命令就可以做出一个符合约定的Makefile,感觉如何?下面开始介绍详细过程:1.创建目录在你的工作目录下创建一个helloworld目录,我们用它来存放helloworld程序和相关文件,比如在/home/my/build下:$mkdirhelloworld$cdhelloworld2、helloworld.c然后用自己喜欢的编辑器写一个hellowrold.c文件,比如命令:vihelloworld.c。使用以下代码作为helloworld.c的内容。#includeintmain(intargc,char**argv){printf("Hello,LinuxWorld!");return0;}完成后保存退出。现在helloworld目录下应该多了一个自己写的helloworld.c。3.生成configure我们使用autoscan命令帮我们根据目录下的源代码生成一个configure.in模板文件。命令:$autoscan$lsconfigure.scanhelloworld.c执行后会在hellowrold目录下生成一个文件:configure.scan,我们可以将其作为configure.in的蓝图。4、生成configure.in现在将configure.scan重命名为configure.in,并进行编辑,按照以下内容修改,去掉无关语句:Code#-*-Autoconf-*-#Processthisfilewithautoconftoproduceaconfigurescript.AC_INIT(helloworld.c)AM_INIT_AUTOMAKE(helloworld,1.0)#Checksforprograms.AC_PROG_CC#Checksforlibraries.#Checksforheaderfiles.#Checksfortypedefs,structures,andcompilercharacteristics.#Checksforlibraryfunctions.AC_OUTPUT(Makefile)5执行aclocal和autoconf,然后分别执行localaclocal4和autoconf两个文件:Code$aclocal$lsaclocal.m4configure.inhelloworld.c$autoconf$lsaclocal.m4autom4te.cacheconfigureconfigure.inhelloworld.c可以看到configure.in中包含了一些宏定义,这些宏在经过autoconfShell脚本处理后会检查系统特性,环境变量,和软件所需的参数。autoconf是一个用来生成自动配置软件源代码脚本(configure)的工具。configure脚本可以独立于autoconf运行,并且在运行过程中不需要用户干预。要生成配置文件,您必须告诉autoconf如何找到您使用的宏。方法是使用aclocal程序生成您的aclocal.m4。aclocal根据configure.in文件的内容自动生成aclocal.m4文件。aclocal是一个perl脚本程序,它的定义是:“aclocal-通过扫描configure.ac创建aclocal.m4”。autoconf从configure.in创建configure,这是一个模板文件,列出了编译软件所需的各种参数。autoconf需要GNUm4宏处理器来处理aclocal.m4并生成配置脚本。m4是一个宏处理器。在扩展宏的同时将输入复制到输出。宏可以是内联的或用户定义的。m4除了可以展开宏外,还内置了一些引用文件、执行命令、整数运算、文本运算、循环等功能,m4可以作为编译器的前端,也可以作为宏单独的处理器。6、新建一个Makefile.am新建一个Makefile.am文件,命令:$viMakefile.am内容如下:代码:AUTOMAKE_OPTIONS=foreignbin_PROGRAMS=helloworldhelloworld_SOURCES=helloworld。cautomake会根据你写的Makefile.am自动生成Makefile.in。Makefile.am中定义的宏和目标将指示automake生成指定的代码。例如,宏bin_PROGRAMS将导致生成已编译和链接的对象。7.运行automake命令:代码:$automake--add-missingconfigure.in:installing`./install-sh'configure.in:installing`./mkinstalldirs'configure.in:installing`./missing'Makefile.am:安装`./depcomp'automake会根据Makefile.am文件生成一些文件,包括最重要的Makefile.in。8、执行configure生成MakefileCode:$./configurecheckingforaBSD-compatibleinstall/usr/bin/install-ccheckingwhetherbuildenvironmentissaneyescheckingforgawkgawkcheckingwhethermakesets$(MAKE)yescheckingforgccgcccheckingforCcompilerdefaultoutputa.outcheckingwhethertheCcompilerworksyescheckingwhetherwearecrosscompilingnocheckingforsuffixofexecutablescheckingforsuffixofobjectfilesocheckingwhetherweareusingtheGNUCcompileryescheckingwhethergccaccepts-gyescheckingforgccoptiontoacceptANSICnoneneededcheckingforstyleofincludeusedbymakeGNUcheckingdependencystyleofgccgcc3configure:creating./config.statusconfig.status:creatingMakefileconfig.status:executingdepfilescommands$ls-lMakefile-rw-rw-r--1yutaoyutao15035Oct1510:40Makefile你可以看到,此时Makefile已经生成出来了。9、使用Makefile编译代码Code$makeifgcc-DPACKAGE_NAME=""-DPACKAGE_TARNAME=""-DPACKAGE_VERSION=""-DPACKAGE_STRING=""-DPACKAGE_BUGREPORT=""-DPACKAGE="helloworld"-DVERSION="1.0"-I.-I.-g-O2-MThelloworld.o-MD-MP-MF".deps/helloworld.Tpo"-c-ohelloworld.o`test-f'helloworld.c'||echo'./'`helloworld.c;thenmv-f".deps/helloworld.Tpo"".deps/helloworld.Po";elserm-f".deps/helloworld.Tpo";exit1;figcc-g-O2-ohelloworldhelloworld.o10,运行helloworldCode$。/helloworld你好,LinuxWorld!这样helloworld就编译好了。如果您按照上述步骤操作,您应该也可以轻松编译出正确的helloworld文件。您也可以尝试使用其他一些make命令,例如makeclean、makeinstall、makedist,看看它们给您带来什么样的效果。你感觉如何?如果你能自己写出这么专业的Makefile,老板肯定会佩服你的。4、深入浅出对于上述命令,我们做一些详细的介绍。1.autoscanautoscan用于扫描源码目录生成configure.scan文件。autoscan可以使用目录名作为参数,但是如果不使用参数,autoscan会认为使用的是当前目录。autoscan将扫描您指定目录中的源文件并创建一个configure.scan文件。2、configure.scanconfigure.scan包含系统配置的基本选项,是一些宏定义。我们需要将其重命名为configure.in3,aclocalaclocal是一个perl脚本。aclocal根据configure.in文件的内容自动生成aclocal.m4文件。aclocal的定义是:“aclocal-通过扫描configure.ac创建aclocal.m4”。4、autoconf使用autoconf根据configure.in和aclocal.m4生成configure文件。configure是一个脚本,可以设置源程序适应各种操作系统平台,并根据不同的系统生成合适的Makefile,让你的源代码可以在不同的操作系统平台上编译。configure.in文件中的内容是一些宏,经过autoconf处理后会变成shell脚本,用于检查系统特性、环境变量、软件必要参数等。configure.in文件中宏的顺序没有指定,但是必须在所有宏的顶部和底部分别添加AC_INIT宏和AC_OUTPUT宏。configure.ini中:#表示注释,这个宏后面的内容会被忽略。AC_INIT(FILE) 这个宏用来查看源代码所在的路径。AM_INIT_AUTOMAKE(PACKAGE,VERSION) 这个宏是必须的,它描述了我们要生成的软件包的名称和版本号:PACKAGE是软件包的名称,VERSION是版本号。当你使用makedist命令时,它会生成一个类似于helloworld-1.0.tar.gz的软件发布包,里面有对应包的名称和版本号。AC_PROG_CC 这个宏会检查系统使用的C编译器。AC_OUTPUT(FILE) 这个宏就是我们要输出的Makefile的名字。我们在使用automake的时候,其实还需要用到一些其他的宏,但是我们可以使用aclocal来帮我们自动生成。执行aclocal后我们会得到aclocal.m4文件。生成configure.in和aclocal.m4这两个宏文件后,我们就可以使用autoconf来生成configure文件了。5、Makefile.amMakefile.am是用来生成Makefile.in的,需要自己手动编写。Makefile.am中定义了一些内容:AUTOMAKE_OPTIONS 这是automake的一个选项。执行automake时,会检查目录下是否有标准GNU软件包中的各种文件,如AUTHORS、ChangeLog、NEWS等文件。当我们设置为foreign时,automake会使用通用软件包的标准来检查。bin_PROGRAMS 这个是指定我们要生成的可执行文件的文件名。如果要生成多个可执行文件,请用空格分隔每个名称。helloworld_SOURCES 指定生成“helloworld”所需的源代码。如果它使用多个源文件,请用空格分隔它们。例如,如果需要helloworld.h和helloworld.c,请写成helloworld_SOURCES=helloworld.hhelloworld.c。如果在bin_PROGRAMS中定义了多个可执行文件,则必须为每个可执行文件定义相对的filename_SOURCES。6.Automake我们使用automake根据configure.in和Makefile.am生成Makefile.in。--add-missing选项的定义是“将缺失的标准文件添加到包中”,这将使automake添加一些标准软件包所必需的文件。automake生成的Makefile.in文件符合GNUMakefile约定,接下来我们只需要执行configureshell脚本就可以生成合适的Makefile。7、Makefile在符合GNUMakefiel约定的Makefile中,包含了一些基本的预定义操作:make 根据Makefile编译源代码,连接,生成目标文件,执行文件。makeclean 清除上次make命令生成的目标文件(后缀为“.o”的文件)和可执行文件。makeinstall 将编译好的可执行文件安装到系统目录下,通常是/usr/local/bin目录。makedist 生成一个分发包文件(即distributionpackage)。该命令将可执行文件及相关文件打包成一个tar.gz压缩文件,作为分发软件的软件包。它将在当前目录中生成一个名为“PACKAGE-VERSION.tar.gz”的文件。PACKAGE和VERSION就是我们在configure.in中定义的AM_INIT_AUTOMAKE(PACKAGE,VERSION)。makedistcheck 生成发布包,并对其进行测试检查,判断发布包的正确性。这个操作会自动解压压缩包文件,然后执行configure命令,执行make确认编译没有错误,最后提示你包已经准备好可以发布了。makedistclean 与makeclean类似,但它也会删除configure生成的所有文件,包括Makefile。5.流程图6.结论通过以上的介绍,你应该可以很容易的生成自己的符合GNU约定的Makefile和相应的工程文件了。如果想写更复杂更习惯的Makefile,可以参考一些开源项目中的configure.in和Makefile.am文件,比如:嵌入式数据库sqlite,单元测试cppunit。