使用Autotools生成Makefile

2019-07-13 04:47发布

  摘自《嵌入式linux应用程序开发详解》第三章 虽然make 项目管理器功能很强大,而且Makefile 可以帮助 make 完成它的使命,但要承认的是,编写 Makefile 确实不是一件轻松的事,尤其对于一个较大的项目而言更是如此。那么,有没有一种轻松的手段生成 Makefile 而同时又能让用户享受 make 的优越性呢?这里要讲述的autotools 系列工具正是为此而设的,它只需用户输入简单的目标文件、依赖文件、文件目录等就可以轻松地生成 Makefile ,这无疑是广大用户的所希望的。另外,这些工具还可以完成系统配置信息的收集,从而可以方便地处理各种移植性的问题。也正是基于此,现在 Linux 上的软件开发一般都用 autotools 来制作 Makefile 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 对自己发布的软件有严格的规范, 比如必须附带许可证声明文件 COPYING ,否则 automake 执行时会报错。automake 提供了 3 种软件等级:foreigngnu 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 自动添加有一些必需的脚本文件。如下所示: [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 之后就可以生成 Makefile.in 文件。 5.运行 configure 在这一步中,通过运行自动配置设置文件 configure, Makefile.in 变成了最终的Makefile。如下所示: [root@localhost automake]# ./configure checking for a BSD-compatible install... /usr/bin/install -c checking whether build enVironment is sane... yes checking for gawk... gawk checking whether make sets $(MAKE)... yes checking for Gcc... Gcc checking for C compiler default output file name... a.out checking whether the C compiler works... yes checking whether we are cross compiling... no checking for suffix of executables... checking for suffix of object files... o checking whether we are using the GNU C compiler... yes checking whether Gcc accepts -g... yes checking for Gcc option to accept ANSI C... none needed checking for style of include used by make... GNU checking dependency style of Gcc... Gcc3 configure: creating ./config.status config.status: creating Makefile config.status: executing depfiles commands 可以看到,在运行 configure 时收集了系统的信息,用户可以在 configure 命令中对其进行 便 ./configure 的自 定义 数有 , 种是 开关 (–enable-XXX –disable-XXX),另一种是开放式,即后面要填入一串字符(–with-XXX=yyyy)参数。读者可以自行尝试其使用方法。另外,读者可以查看同一目录下的“config.log”文件,以方便调试之用。到此为止,makefile 就可以自动生成了。回忆整个步骤,用户不再需要定制不同的规则,而只需要输入简单的文件及目录名即可,这样就大大方便了用户的使用autotools 生成Makefile

使用 autotools 所生成的 Makefile autotools 生成的 Makefile 除具有普通的编译功能外,还具有以下主要功能(感兴趣的读者可以查看这个简单的 hello.c 程序的 makefile) 1.make 键入 make 默认执行“make all”命令,即目标体为 all,其执行情况如下所示: [root@localhost automake]# make 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 此时在本目录下就生成了可执行文件“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 来制作的。