转载于:http://blog.dccmx.com/2011/01/autoscan/
--------------------------------------------------------------------------------------------------------------
前面说了autotools的基本原理:将configure.ac里的宏展开,运行,生成Makefile。其实,对于大多数项目来说,configure.ac里的内容基本框架都差不多。既然都差不多那么有没有什么工具可以帮我们做这些基本的事情呢?别忘了你在linux下,有!
autoscan就是干这事的。
下面我们建个test项目吧。目录如下:1
2
3
4
5 test
├── README
└── src
├── client.c
└── server.c
在test目录下运行autoscan看看。是不是生成了如下的configure.scan呢(autoscan.log被我们无情的忽略了):
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.68])
AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS])
AC_CONFIG_SRCDIR([src/server.c])
AC_CONFIG_HEADERS([config.h])
# Checks for programs.
AC_PROG_CC
# Checks for libraries.
# Checks for header files.
AC_CHECK_HEADERS([netinet/in.h stdlib.h strings.h sys/socket.h unistd.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_TYPE_PID_T
# Checks for library functions.
AC_FUNC_FORK
AC_FUNC_MALLOC
AC_CHECK_FUNCS([bzero socket])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
我们把这个文件稍微改改,即可用来当做configure.ac了,先将它重命名为configure.ac吧。
我们解释一下这个文件里的一些宏。
首先是,AC_PREREQ([2.68]),这个宏用来检查你机器上的autoconf版本的。这里是我机器上的版本号2.68。
然后AC_INIT宏,这里你要将里面的内容改改,里面的提示你懂的。我们改成下面这样:
AC_INIT([test], [0.1], [dccmx@test.com])
紧跟着是AC_CONFIG_SRCDIR([src/server.c]),这是autoconf用来定位自己的所在目录的宏,里面的内容是所在目录下的任意一个文件就可以了,你可以改成一个更能代表你项目的文件(这样不会更其他项目冲突),也可以不动。
下面是AC_CONFIG_HEADERS([config.h]) 这个是用来生成标准的config.h头文件的宏,这个宏的意思是,从将模板里的@***@变量替换掉生成config.h头文件。模板是什么?默认是*.in,你记得的(Makefile.in),这里就是config.h.in。我们稍后还会提到。
下面就是一系列的check了,最后是生成Makefile的文件,我们介绍过。
好了,改完了,autoconf命令看看吧。
autoconf如愿生成了configure,运行configure,是不是很标准的输出呢,但是最后提示错了,因为我们还没有添加config.h.in和Makefile.in
Makefile.in文件还像以前的:
all: @PACKAGE_NAME@_client @PACKAGE_NAME@_server
gcc -o @PACKAGE_NAME@_client src/client.c
@PACKAGE_NAME@_server:
gcc -o @PACKAGE_NAME@_server src/server.c
config.h.in呢?我们写一个吧,从上面autoscan生成的configure.ac来看,宏AC_CHECK_HEADERS([netinet/in.h stdlib.h strings.h sys/socket.h unistd.h])告诉我们的程序调用了这些头文件,那么我们的config.h.in就这样写:
#undef HAVE_NETINET_IN_H
#undef HAVE_STDINT_H
#undef HAVE_STDIO_H
#undef HAVE_STDLIB_H
#undef HAVE_STRING_H
#undef HAVE_SYS_SOCKET_H
#undef HAVE_UNISTD_H
#undef HAVE_NONEXIST_H
看到啦,我们先把这些头文件全都按规则undef掉,我们还加了个系统不存在的头文件试试,现在在运行configure脚本看看,是不是出现了下面的config.h头文件呢:
/* config.h. Generated from config.h.in by configure. */
#define HAVE_NETINET_IN_H 1
#define HAVE_STDINT_H 1
#define HAVE_STDIO_H 1
#define HAVE_STDLIB_H 1
#define HAVE_STRING_H 1
#define HAVE_SYS_SOCKET_H 1
#define HAVE_UNISTD_H 1
/* #undef HAVE_NONEXIST_H */
看,所有存在的头文件都被define成了1,不存在的被注释掉。好吧,在你的程序里尽情的include吧,生活真美好。现在可以make生成可执行文件了。test_client和test_server是不是如愿生成了呢?应该是的!
现在我们项目中仍然有两个.in文件要我们自己写:config.h.in和Makefile.in,关于这两个文件的工具,我们后面再谈。拉上老婆出去逛逛吧。歇会儿。