Linux系统编程之autoconf与automake自动生成Makefile文件

GNU make是一个命令工具,它解释Makefile 中的指令。Makefile文件描述了整个工程所有文件的编译顺序、编译规则,Makefile有自己的书写格式、关键字、函数。Linux系统编程人员可以利用autoconf和automake自动生成一个符合惯例的Makefile。

下面就是示例说明Makefile文件自动生成过程,源文件如下:

/* common.h */
#ifndef COMMON_H
#define COMMON_H

int add(int, int);
int sub(int, int);
int mul(int, int);
int div(int, int);

#endif

/* add.c */
#include "common.h"

int add(int i, int j)
{
	return i + j;
}

/* sub.c */
#include "common.h"

int sub(int i, int j)
{
	return i - j;
}

/* mul.c */
#include "common.h"

int mul(int i, int j)
{
	return i * j;
}

/* div.c */
#include "common.h"

int div(int i, int j)
{
	return i / j;
}

/* main.c */
#include <stdio.h>
#include "common.h"

int main(void)
{
	int i = 200, j = 10;
	int a, s, m, d;

	a = add(i, j);
	s = sub(i, j);
	m = mul(i, j);
	d = div(i, j);

	printf("%d + %d = %d\n", i, j, a);
	printf("%d - %d = %d\n", i, j, s);
	printf("%d * %d = %d\n", i, j, m);
	printf("%d / %d = %d\n", i, j, d);

	return 0;
}

一、autoscan命令
autoscan: 扫描源代码以搜寻普通的可移植性问题,比如检查编译器,库,头文件等,生成文件configure.scan,它是configure.ac的一个雏形。

[ycxie@fedora netdev]$ ll
total 24
-rwxrwxr-x. 1 ycxie ycxie  62 May  2 15:56 add.c
-rwxrwxr-x. 1 ycxie ycxie 119 May  2 15:56 common.h
-rwxrwxr-x. 1 ycxie ycxie  62 May  2 15:56 div.c
-rwxrwxr-x. 1 ycxie ycxie 320 May  2 15:56 main.c
-rwxrwxr-x. 1 ycxie ycxie  62 May  2 15:56 mul.c
-rwxrwxr-x. 1 ycxie ycxie  62 May  2 15:56 sub.c
[ycxie@fedora netdev]$ autoscan
[ycxie@fedora netdev]$ ll
total 28
-rwxrwxr-x. 1 ycxie ycxie  62 May  2 15:56 add.c
-rw-rw-r--. 1 ycxie ycxie   0 May  2 16:11 autoscan.log
-rwxrwxr-x. 1 ycxie ycxie 119 May  2 15:56 common.h
-rw-rw-r--. 1 ycxie ycxie 465 May  2 16:11 configure.scan
-rwxrwxr-x. 1 ycxie ycxie  62 May  2 15:56 div.c
-rwxrwxr-x. 1 ycxie ycxie 320 May  2 15:56 main.c
-rwxrwxr-x. 1 ycxie ycxie  62 May  2 15:56 mul.c
-rwxrwxr-x. 1 ycxie ycxie  62 May  2 15:56 sub.c

二、将configure.scan文件名改为configure.ac,并修改内容
AC_PREREQ:宏声明本文件要求的autoconf版本,本例使用的版本为2.69。
AC_INIT:宏用来定义软件的名称和版本等信息,”FULL-PACKAGE-NAME”为软件包名称,”VERSION”为软件版本号,”BUG-REPORT-ADDRESS”为BUG报告地址(一般为软件作者邮件地址)。
AC_CONFIG_SRCDIR:宏用来侦测所指定的源码文件是否存在,来确定源码目录的有效性。
AC_CONFIG_HEADER:宏用于生成config.h文件,以便autoheader使用。
AC_PROG_CC:用来指定编译器,如果不指定,选用默认gcc。
AC_OUTPUT:用来设定configure所要产生的文件,如果是Makefile,configure会把它检查出来的结果带入Makefile.in文件产生合适的Makefile。使用Automake时,还需要一些其他的参数,这些额外的宏用aclocal工具产生。

[ycxie@fedora netdev]$ mv configure.scan configure.ac
[ycxie@fedora netdev]$ vim configure.ac
[ycxie@fedora netdev]$ cat configure.ac
#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_PREREQ([2.69])
AC_INIT([netdev], [1.0], [admin@xieyincai.com])
AM_INIT_AUTOMAKE
AC_CONFIG_SRCDIR([main.c])
AC_CONFIG_HEADERS([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_OUTPUT([Makefile])

三、aclocal命令
aclocal:根据已经安装的宏,用户定义宏和acinclude.m4文件中的宏将configure.ac文件所需要的宏集中定义到文件 aclocal.m4中。aclocal是一个perl脚本程序,它的定义是:“aclocal – create aclocal.m4 by scanning configure.ac”

[ycxie@fedora netdev]$ aclocal
[ycxie@fedora netdev]$ ll
total 76
-rw-rw-r--. 1 ycxie ycxie 41888 May  2 16:25 aclocal.m4
-rwxrwxr-x. 1 ycxie ycxie    62 May  2 15:56 add.c
drwxr-xr-x. 2 ycxie ycxie  4096 May  2 16:25 autom4te.cache
-rw-rw-r--. 1 ycxie ycxie     0 May  2 16:11 autoscan.log
-rwxrwxr-x. 1 ycxie ycxie   119 May  2 15:56 common.h
-rw-rw-r--. 1 ycxie ycxie   481 May  2 16:25 configure.ac
-rwxrwxr-x. 1 ycxie ycxie    62 May  2 15:56 div.c
-rwxrwxr-x. 1 ycxie ycxie   320 May  2 15:56 main.c
-rwxrwxr-x. 1 ycxie ycxie    62 May  2 15:56 mul.c
-rwxrwxr-x. 1 ycxie ycxie    62 May  2 15:56 sub.c

四、autoconf命令
autoconf:将configure.ac中的宏展开,生成configure脚本。这个过程可能要用到aclocal.m4中定义的宏。

[ycxie@fedora netdev]$ autoconf
[ycxie@fedora netdev]$ ll
total 220
-rw-rw-r--. 1 ycxie ycxie  41888 May  2 16:25 aclocal.m4
-rwxrwxr-x. 1 ycxie ycxie     62 May  2 15:56 add.c
drwxr-xr-x. 2 ycxie ycxie   4096 May  2 16:27 autom4te.cache
-rw-rw-r--. 1 ycxie ycxie      0 May  2 16:11 autoscan.log
-rwxrwxr-x. 1 ycxie ycxie    119 May  2 15:56 common.h
-rwxrwxr-x. 1 ycxie ycxie 145764 May  2 16:27 configure
-rw-rw-r--. 1 ycxie ycxie    481 May  2 16:25 configure.ac
-rwxrwxr-x. 1 ycxie ycxie     62 May  2 15:56 div.c
-rwxrwxr-x. 1 ycxie ycxie    320 May  2 15:56 main.c
-rwxrwxr-x. 1 ycxie ycxie     62 May  2 15:56 mul.c
-rwxrwxr-x. 1 ycxie ycxie     62 May  2 15:56 sub.c

五、autoheader命令
autoheader生成了configure.h.in如果在configure.ac中定义了AC_CONFIG_HEADER,那么此文件就需要。

[ycxie@fedora netdev]$ autoheader
[ycxie@fedora netdev]$ ll
total 224
-rw-rw-r--. 1 ycxie ycxie  41888 May  2 16:25 aclocal.m4
-rwxrwxr-x. 1 ycxie ycxie     62 May  2 15:56 add.c
drwxr-xr-x. 2 ycxie ycxie   4096 May  2 16:27 autom4te.cache
-rw-rw-r--. 1 ycxie ycxie      0 May  2 16:11 autoscan.log
-rwxrwxr-x. 1 ycxie ycxie    119 May  2 15:56 common.h
-rw-rw-r--. 1 ycxie ycxie    625 May  2 16:29 config.h.in
-rwxrwxr-x. 1 ycxie ycxie 145764 May  2 16:27 configure
-rw-rw-r--. 1 ycxie ycxie    481 May  2 16:25 configure.ac
-rwxrwxr-x. 1 ycxie ycxie     62 May  2 15:56 div.c
-rwxrwxr-x. 1 ycxie ycxie    320 May  2 15:56 main.c
-rwxrwxr-x. 1 ycxie ycxie     62 May  2 15:56 mul.c
-rwxrwxr-x. 1 ycxie ycxie     62 May  2 15:56 sub.c

六、创建Makefile.am文件
AUTOMAKE_OPTIONS:为设置Automake的选项。由于GNU对自己发布的软件有严格的规范,比如必须附带许可证声明文件COPYING等,否则Automake执行时会报错。Automake提供了3种软件等级:foreign、gnu和gnits,供用户选择,默认等级为gnu。本例使需用foreign等级,它只检测必须的文件。
bin_PROGRAMS:定义要产生的执行文件名。如果要产生多个执行文件,每个文件名用空格隔开。
netdev_SOURCES:定义“netdev”这个执行程序所需要的原始文件。如果“netdev”这个程序是由多个原始文件所产生的,则必须把它所用到的所有原始文件都列出来,并用空格隔开。

[ycxie@fedora netdev]$ vim Makefile.am
[ycxie@fedora netdev]$ cat Makefile.am
AUTOMAKE_OPTIONS = foreign
bin_PROGRAMS = netdev
netdev_SOURCES = main.c add.c sub.c mul.c div.c common.h

七、automake命令
automake:将Makefile.am中定义的结构建立Makefile.in,然后configure脚本将生成的Makefile.in文件转换为Makefile。如果在configure.ac中定义了一些特殊的宏,比如AC_PROG_LIBTOOL,它会调用libtoolize,否则它会自己产生config.guess和config.sub。此步主要是为了生成Makefile.in,加上–add-missing参数后,会补全缺少的脚本。

[ycxie@fedora netdev]$ automake --add-missing
configure.ac:11: installing './compile'
configure.ac:6: installing './install-sh'
configure.ac:6: installing './missing'
Makefile.am: installing './depcomp'
[ycxie@fedora netdev]$ ll
total 256
-rw-rw-r--. 1 ycxie ycxie  41888 May  2 16:25 aclocal.m4
-rwxrwxr-x. 1 ycxie ycxie     62 May  2 15:56 add.c
drwxr-xr-x. 2 ycxie ycxie   4096 May  2 16:36 autom4te.cache
-rw-rw-r--. 1 ycxie ycxie      0 May  2 16:11 autoscan.log
-rwxrwxr-x. 1 ycxie ycxie    119 May  2 15:56 common.h
lrwxrwxrwx. 1 ycxie ycxie     32 May  2 16:36 compile -> /usr/share/automake-1.16/compile
-rw-rw-r--. 1 ycxie ycxie    625 May  2 16:29 config.h.in
-rwxrwxr-x. 1 ycxie ycxie 145764 May  2 16:27 configure
-rw-rw-r--. 1 ycxie ycxie    481 May  2 16:25 configure.ac
lrwxrwxrwx. 1 ycxie ycxie     32 May  2 16:36 depcomp -> /usr/share/automake-1.16/depcomp
-rwxrwxr-x. 1 ycxie ycxie     62 May  2 15:56 div.c
lrwxrwxrwx. 1 ycxie ycxie     35 May  2 16:36 install-sh -> /usr/share/automake-1.16/install-sh
-rwxrwxr-x. 1 ycxie ycxie    320 May  2 15:56 main.c
-rw-rw-r--. 1 ycxie ycxie    107 May  2 16:35 Makefile.am
-rw-rw-r--. 1 ycxie ycxie  24902 May  2 16:36 Makefile.in
lrwxrwxrwx. 1 ycxie ycxie     32 May  2 16:36 missing -> /usr/share/automake-1.16/missing
-rwxrwxr-x. 1 ycxie ycxie     62 May  2 15:56 mul.c
-rwxrwxr-x. 1 ycxie ycxie     62 May  2 15:56 sub.c

八、执行configure生成Makefile

[ycxie@fedora netdev]$ ./configure
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /usr/bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking whether make supports nested variables... yes
checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables... 
checking whether we are cross compiling... no
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 ISO C89... none needed
checking whether gcc understands -c and -o together... yes
checking whether make supports the include directive... yes (GNU style)
checking dependency style of gcc... gcc3
checking that generated files are newer than configure... done
configure: creating ./config.status
config.status: creating Makefile
config.status: creating config.h
config.status: executing depfiles commands
[ycxie@fedora netdev]$ ll
total 332
-rw-rw-r--. 1 ycxie ycxie  41888 May  2 16:25 aclocal.m4
-rwxrwxr-x. 1 ycxie ycxie     62 May  2 15:56 add.c
drwxr-xr-x. 2 ycxie ycxie   4096 May  2 16:36 autom4te.cache
-rw-rw-r--. 1 ycxie ycxie      0 May  2 16:11 autoscan.log
-rwxrwxr-x. 1 ycxie ycxie    119 May  2 15:56 common.h
lrwxrwxrwx. 1 ycxie ycxie     32 May  2 16:36 compile -> /usr/share/automake-1.16/compile
-rw-rw-r--. 1 ycxie ycxie    769 May  2 16:39 config.h
-rw-rw-r--. 1 ycxie ycxie    625 May  2 16:29 config.h.in
-rw-rw-r--. 1 ycxie ycxie   9170 May  2 16:39 config.log
-rwxrwxr-x. 1 ycxie ycxie  32463 May  2 16:39 config.status
-rwxrwxr-x. 1 ycxie ycxie 145764 May  2 16:27 configure
-rw-rw-r--. 1 ycxie ycxie    481 May  2 16:25 configure.ac
lrwxrwxrwx. 1 ycxie ycxie     32 May  2 16:36 depcomp -> /usr/share/automake-1.16/depcomp
-rwxrwxr-x. 1 ycxie ycxie     62 May  2 15:56 div.c
lrwxrwxrwx. 1 ycxie ycxie     35 May  2 16:36 install-sh -> /usr/share/automake-1.16/install-sh
-rwxrwxr-x. 1 ycxie ycxie    320 May  2 15:56 main.c
-rw-rw-r--. 1 ycxie ycxie  24502 May  2 16:39 Makefile
-rw-rw-r--. 1 ycxie ycxie    107 May  2 16:35 Makefile.am
-rw-rw-r--. 1 ycxie ycxie  24902 May  2 16:36 Makefile.in
lrwxrwxrwx. 1 ycxie ycxie     32 May  2 16:36 missing -> /usr/share/automake-1.16/missing
-rwxrwxr-x. 1 ycxie ycxie     62 May  2 15:56 mul.c
-rw-rw-r--. 1 ycxie ycxie     23 May  2 16:39 stamp-h1
-rwxrwxr-x. 1 ycxie ycxie     62 May  2 15:56 sub.c

上面八步已经自动生成Makefile文件,至此大功告成。下面我们就来测试一下:

[ycxie@fedora netdev]$ make
make  all-am
make[1]: Entering directory '/home/ycxie/Workspace/netdev'
gcc -DHAVE_CONFIG_H -I.     -g -O2 -MT main.o -MD -MP -MF .deps/main.Tpo -c -o main.o main.c
mv -f .deps/main.Tpo .deps/main.Po
gcc -DHAVE_CONFIG_H -I.     -g -O2 -MT add.o -MD -MP -MF .deps/add.Tpo -c -o add.o add.c
mv -f .deps/add.Tpo .deps/add.Po
gcc -DHAVE_CONFIG_H -I.     -g -O2 -MT sub.o -MD -MP -MF .deps/sub.Tpo -c -o sub.o sub.c
mv -f .deps/sub.Tpo .deps/sub.Po
gcc -DHAVE_CONFIG_H -I.     -g -O2 -MT mul.o -MD -MP -MF .deps/mul.Tpo -c -o mul.o mul.c
mv -f .deps/mul.Tpo .deps/mul.Po
gcc -DHAVE_CONFIG_H -I.     -g -O2 -MT div.o -MD -MP -MF .deps/div.Tpo -c -o div.o div.c
mv -f .deps/div.Tpo .deps/div.Po
gcc  -g -O2   -o netdev main.o add.o sub.o mul.o div.o  
make[1]: Leaving directory '/home/ycxie/Workspace/netdev'
[ycxie@fedora netdev]$ ./netdev
200 + 10 = 210
200 - 10 = 190
200 * 10 = 2000
200 / 10 = 20

1 thought on “Linux系统编程之autoconf与automake自动生成Makefile文件

  1. 龙的传人

    经典,太详细了。自动生成Makefile文件成功,目测有效,感谢!

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *