本文主要是介绍【转】Linux下autoconf和automake使用 (make),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
http://www.cnblogs.com/itech/archive/2010/11/28/1890220.htm
作为Linux下的程序开发人员,一定都遇到过Makefile,用make命令来编译自己写的程序确实是很方便。一般情况下,大家都是手工写一个简单Makefile,如果要想写出一个符合自由软件惯例的Makefile就不那么容易了. 在本文中,将介绍如何使用autoconf和automake两个工具来帮助我们自动地生成符合自由软件惯例的Makefile,这样就可以象常见的GNU程序一样,只要使用“./configure”,“make”,“make instal”就可以把程序安装到Linux系统中去了。这将特别适合想做开放源代码软件的程序开发人员,又或如果你只是自己写些小的Toy程序,那么这个文章对你也会有很大的帮助。
一、Makefile介绍
Makefile是用于自动编译和链接的,一个工程有很多文件组成,每一个文件的改变都会导致工程的重新链接,但是不是所有的文件都需要重新编译,Makefile中纪录有文件的信息,在make时会决定在链接的时候需要重新编译哪些文件。
Makefile的宗旨就是:让编译器知道要编译一个文件需要依赖其他的哪些文件。当那些依赖文件有了改变,编译器会自动的发现最终的生成文件已经过时,而重新编译相应的模块。
Makefile的基本结构不是很复杂,但当一个程序开发人员开始写Makefile时,经常会怀疑自己写的是否符合惯例,而且自己写的Makefile经常和自己的开发环境相关联,当系统环境变量或路径发生了变化后,Makefile可能还要跟着修改。这样就造成了手工书写Makefile的诸多问题,automake恰好能很好地帮助我们解决这些问题。
使用automake,程序开发人员只需要写一些简单的含有预定义宏的文件,由autoconf根据一个宏文件生成configure,由automake根据另一个宏文件生成Makefile.in,再使用configure依据Makefile.in来生成一个符合惯例的Makefile。下面我们将详细介绍Makefile的automake生成方法。
(概括:
1——》写一些含有预定义宏的文件
2——》autoconf根据这个宏文件生成configure
3——》automake根据另一个宏文件生成Makefile.in
4——》使用configure根据Makefile.in生成一个符合惯例的makefile)
二、使用的环境
本文所提到的程序是基于Linux发行版本:Fedora Core release 1,它包含了我们要用到的autoconf,automake。
三、从helloworld入手
我们从大家最常使用的例子程序helloworld开始。
下面的过程如果简单地说来就是:
新建三个文件: helloworld.c configure.in Makefile.am
然后执行:autoscan; aclocal; autoconf; automake --add-missing; ./configure; make; ./helloworld;
就可以看到Makefile被产生出来,而且可以将helloworld.c编译通过。很简单吧,几条命令就可以做出一个符合惯例的Makefile,感觉如何呀。现在开始介绍详细的过程:
1、建目录
在你的工作目录下建一个helloworld目录,我们用它来存放helloworld程序及相关文件,如在/home/my/build下:
$ mkdir helloword
$ cd helloworld
2、 helloworld.c
然后用你自己最喜欢的编辑器写一个hellowrold.c文件,如命令:vi helloworld.c。使用下面的代码作为helloworld.c的内容。
int main(int argc, char** argv)
{
printf("Hello, Linux World! ");
return 0;
}
完成后保存退出。现在在helloworld目录下就应该有一个你自己写的helloworld.c了。
3、生成configure
我们使用autoscan命令来帮助我们根据目录下的源代码生成一个configure.in的模板文件。
命令:
$ autoscan
$ ls
configure.scan helloworld.c
执行后在hellowrold目录下会生成一个文件:configure.scan,我们可以拿它作为configure.in的蓝本。
4,生成configure.in
现在将configure.scan改名为configure.in,并且编辑它,按下面的内容修改,去掉无关的语句:
autotools使用流程 正如前面所言,autotools是系列工具,读者首先要确认系统是否装了以下工具(可以用which命令进行查看)。 · aclocal · autoscan · autoconf · autoheader · automake 使用autotools主要就是利用各个工具的脚本文件以生成最后的Makefile。其总体流程是这样的: · 使用aclocal生成一个“aclocal.m4”文件,该文件主要处理本地的宏定义; · 改写“configure.scan”文件,并将其重命名为“configure.in”,并使用autoconf文件生成configure文件。 接下来,笔者将通过一个简单的hello.c例子带领读者熟悉autotools生成makefile的过程,由于在这过程中有涉及到较多的脚本文件,为了更清楚地了解相互之间的关系,强烈建议读者实际动手操作以体会其整个过程。 1.autoscan 它会在给定目录及其子目录树中检查源文件,若没有给出目录,就在当前目录及其子目录树中进行检查。它会搜索源文件以寻找一般的移植性问题并创建一个 文件“configure.scan”,该文件就是接下来autoconf要用到的“configure.in”原型。如下所示: [root@localhost automake]# autoscan autom4te: configure.ac: no such file or directory autoscan: /usr/bin/autom4te failed with exit status: 1 [root@localhost automake]# ls autoscan.log configure.scan hello.c 如上所示,autoscan首先会尝试去读入“configure.ac”(同configure.in的配置文件)文件,此时还没有创建该配置文件,于是它会自动生成一个“configure.in”的原型文件“configure.scan”。 2.autoconf configure.in是autoconf的脚本配置文件,它的原型文件“configure.scan”如下所示: # -*- Autoconf -*- # Process this file with autoconf to produce a configure script. AC_PREREQ(2.59) #The next one is modified by sunq #AC_INIT(FULL-PACKAGE-NAME,VERSION,BUG-REPORT-ADDRESS) AC_INIT(hello,1.0) # The next one is added by sunq AM_INIT_AUTOMAKE(hello,1.0) AC_CONFIG_SRCDIR([hello.c]) AC_CONFIG_HEADER([config.h]) # Checks for programs. AC_PROG_CC # Checks for libraries. # Checks for header files. # Checks for typedefs, structures, and compiler characteristics. # Checks for library functions. AC_CONFIG_FILES([Makefile]) AC_OUTPUT 下面对这个脚本文件进行解释: · 以“#”号开始的行为注释。 · AC_PREREQ宏声明本文件要求的autoconf版本,如本例使用的版本2.59。 · AC_INIT宏用来定义软件的名称和版本等信息,在本例中省略了BUG-REPORT-ADDRESS,一般为作者的e-mail。 · AM_INIT_AUTOMAKE是笔者另加的,它是automake所必备的宏,也同前面一样,PACKAGE是所要产生软件套件的名称,VERSION是版本编号。 · AC_CONFIG_SRCDIR宏用来侦测所指定的源码文件是否存在,来确定源码目录的有 效性。在此处为当前目录下的hello.c。 · AC_CONFIG_HEADER宏用于生成config.h文件,以便autoheader使用。 · AC_CONFIG_FILES宏用于生成相应的Makefile文件。 · 中间的注释间可以添加分别用户测试程序、测试函数库、测试头文件等宏定义。 接下来首先运行aclocal,生成一个“aclocal.m4”文件,该文件主要处理本地的宏定义。如下所示: [root@localhost automake]# aclocal 再接着运行autoconf,生成“configure”可执行文件。如下所示: [root@localhost automake]# autoconf [root@localhost automake]# ls aclocal.m4 autom4te.cache autoscan.log configure configure.in hello.c 3.autoheader 接着使用autoheader命令,它负责生成config.h.in文件。该工具通常会从“acconfig.h”文件中复制用户附加的符号定义,因此此处没有附加符号定义,所以不需要创建“acconfig.h”文件。如下所示: [root@localhost automake]# autoheader 4.automake 这一步是创建Makefile很重要的一步,automake要用的脚本配置文件是Makefile.am,用户需要自己创建相应的文件。之后,automake工具转换成Makefile.in。在该例中,笔者创建的文件为Makefile.am如下所示: AUTOMAKE_OPTIONS=foreign bin_PROGRAMS= hello hello_SOURCES= hello.c 下面对该脚本文件的对应项进行解释。 · 其中的AUTOMAKE_OPTIONS为设置automake的选项。由于GNU(在第1章中已经有所介绍)对自己发布的软件有严格的规范,比如必须附 带许可证声明文件COPYING等,否则automake执行时会报错。automake提供了三种软件等级:foreign、gnu和gnits,让用 户选择采用,默认等级为gnu。在本例使用foreign等级,它只检测必须的文件。 · bin_PROGRAMS定义要产生的执行文件名。如果要产生多个执行文件,每个文件名用空格隔开。 · hello_SOURCES定义“hello”这个执行程序所需要的原始文件。如果”hello”这个程序是由多个原始文件所产生的,则必须把它所用到的 所有原始文件都列出来,并用空格隔开。例如:若目标体“hello”需要“hello.c”、“sunq.c”、“hello.h”三个依赖文件,则定义 hello_SOURCES=hello.c sunq.c hello.h。要注意的是,如果要定义多个执行文件,则对每个执行程序都要定义相应的file_SOURCES。 接下来可以使用automake对其生成“configure.in”文件,在这里使用选项“—adding-missing”可以让automake自动添加有一些必需的脚本文件。如下所示: 最上层的要写明 AUTOMAKE_OPTIONS = foreign 如果这个目录没有要编译的文件,只包含了子目录,则只写个 SUBDIRS = dir1 就ok了。 例如我的工程,最上层只是包含了源码目录,于是就写了 AUTOMAKE_OPTIONS=foreign SUBDIRS=src 如果有文件要编译,则要指明target 先。比如我的src目录底下既有文件,又有目录,而src的这层目录中的文件最后是要编译成一个 可执行文件,则src目录下的Makefile.am这么写。 bin_PROGRAMS= myprogram SUBDIRS= sub1 myprogram_SOURCES= \ a.cpp\ b.cpp\ # 要编译的源文件。这儿的_SOURCES是关键字 EXTRA_DIST= \ a.h \ b.h # 不用编成.o,但生成target myprogram也需要给编译器处理的头文件放这里 myprogram_LDADD = libsub1.a 这个_LDADD是关键字, # 最后生成myprogram这个执行文件,还要link src/sub1这个目录中的内容编成的一个lib :libsub1.a, myprogram_LDFLAGS = -lpthread -lglib-2.0 -L/usr/bin $(all_libraries) # myprogram还要link系统中的动态so,以此类推,需要连自编译的so,也写到这个关键字 _LDFLAGS后面就好了。 AM_CXXFLAGS = -D_LINUX # 传递给g++编译器的一些编译宏定义,选项, INCLUDES=-IPassport -Isub1/ -I/usr/include/glib-2.0\ -I/usr/lib/glib-2.0/include $(all_includes) # 传递给编译器的头文件路径。 下面是sub1种生成lib的Makefile.am noinst_LIBRARIES = libprotocol.a # 不是生成可执行文件,而是静态库,target用noinst_LIBRARIES libprotocol_a_SOURCES = \ alib.cpp EXTRA_DIST = mylib.h\ alib.h INCLUDES= -I../ $(all_includes) AM_CXXFLAGS = -D_LINUX -DONLY_EPOLL -D_SERVER ok ,最后补上AC_PROG_RANLIB涵义,如果要自己生成lib,然后link到最终的可执行文件中,则要加上这个宏,否则不用。 2 一点讨论 每个目录至少都要有一个target,或者是可执行文件或者是lib,似乎对目录的划分带来点局限。比如我的目录结构如果是这样 ./Src ./Src/sub1 ./Src/sub2 而我想这样,sub1,sub2都没有target,目录划分只是为了区别代码的不同模块,然后把两个目录中编译出的中间文件一起link ,得到最后需要的 myprogram 。 似乎在Src/Makefile.am中要这么写 myprogram_SOURCES = sub1/a.cpp \ sub2/b.cpp [root@localhost automake]# automake --add-missing configure.in: installing ''./install-sh'' configure.in: installing ''./missing'' Makefile.am: installing ''depcomp'' [root@localhost automake]# ls aclocal.m4 autoscan.log configure.in hello.c Makefile.am missing autom4te.cache configure depcomp install-sh Makefile.in config.h.in 可以看到,在automake之后就可以生成configure.in文件。 5.运行configure 在这一步中,通过运行自动配置设置文件configure,把Makefile.in变成了最终的Makefile。如下所示: [root@localhost automake]# ./configure 可以看到,在运行configure时收集了系统的信息,用户可以在configure命令中对其进行方便地配置。在./configure的自定 义参数有两种,一种是开关式(--enable-XXX或--disable-XXX),另一种是开放式,即后面要填入一串字符(--with- XXX=yyyy)参数。读者可以自行尝试其使用方法。另外,读者可以查看同一目录下的”config.log”文件,以方便调试之用。 到此为止,makefile就可以自动生成了。回忆整个步骤,用户不再需要定制不同的规则,而只需要输入简单的文件及目录名即可,这样就大大方便了用户的使用。下面的图3.9总结了上述过程: 图3.9 autotools生成Makefile流程图 使用autotools所生成的Makefile autotools生成的Makefile除具有普通的编译功能外,还具有以下主要功能(感兴趣的读者可以查看这个简单的hello.c程序的makefile): 1.make 键入make默认执行”make all”命令,即目标体为all,其执行情况如下所示: [root@localhost automake]# make 此时在本目录下就生成了可执行文件“hello”,运行“./hello”能出现正常结果,如下所示: [root@localhost automake]# ./hello Hello!Autoconf! 2.make install 此时,会把该程序安装到系统目录中去,如下所示: [root@localhost automake]# make install if Gcc -DPACKAGE_NAME=\"\" -DPACKAGE_TARNAME=\"\" -DPACKAGE_VERSION=\"\" -DPACKAGE_STRING=\"\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE=\"hello\" -DVERSION=\"1.0\" -I. -I. -g -O2 -MT hello.o -MD -MP -MF ".deps/hello.Tpo" -c -o hello.o hello.c; \ then mv -f ".deps/hello.Tpo" ".deps/hello.Po"; else rm -f ".deps/hello.Tpo"; exit 1; fi Gcc -g -O2 -o hello hello.o make[1]: Entering directory ''/root/workplace/automake'' test -z "/usr/local/bin" || mkdir -p -- "/usr/local/bin" /usr/bin/install -c ''hello'' ''/usr/local/bin/hello'' make[1]: Nothing to be done for ''install-data-am''. make[1]: LeaVing directory ''/root/workplace/automake'' 此时,若直接运行hello,也能出现正确结果,如下所示: [root@localhost automake]# hello Hello!Autoconf! 3.make clean 此时,make会清除之前所编译的可执行文件及目标文件(object file, *.o),如下所示: [root@localhost automake]# make clean test -z "hello" || rm -f hello rm -f *.o 4.make dist 此时,make将程序和相关的文档打包为一个压缩文档以供发布,如下所示: [root@localhost automake]# make dist [root@localhost automake]# ls hello-1.0-tar.gz hello-1.0-tar.gz 可见该命令生成了一个hello-1.0-tar.gz的压缩文件。 由上面的讲述读者不难看出,autotools确实是软件维护与发布的必备工具,也鉴于此,如今GUN的软件一般都是由automake来制作的。
这篇关于【转】Linux下autoconf和automake使用 (make)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!