1. 引言
我们在学习和使用很多开源软件的时候,会发现其源码中并不总是有现成的configure文件和makefile文件,而是需要先执行一个安装脚本。例如,SOHO-DBproxy中,使用build.sh完成编译安装:
sh autogen.sh
bash ./configure --prefix=${MYSQL_PROXY_INSTALL_PATH} --with-mysql=${MYSQL_INSTALL_PATH}/bin/mysql_config
make && make install && mkdir -p ${MYSQL_PROXY_INSTALL_PATH}/var/log && \
cp -r ./etc ${MYSQL_PROXY_INSTALL_PATH}/etc && chmod 600 ${MYSQL_PROXY_INSTALL_PATH}/etc/mysql-proxy.cnf
我们看到,其在运行configure之前先调用了aotugen.sh。这里面的内容就是本文要讲的,自动化编译工具GNU autoconf 和 automake。
2. 工具简介
软件环境:autoconf/automake/m4/perl/libtool
autoconf:生成自动配置的源码包,依赖于m4
automake:依赖Makefile.am生成Makefile.in,需要使用到perl
libtool:用于生成各种工具库
目前automake支持三种目录层次:
flat:源文件、库文件等都在同一目录
shallow:主要源文件在顶层,其余文件在底层
deep:顶层不包含源代码,主要代码都在底层文件夹中
3.使用实例
首先我们看一下流程图
下面以自己写的一段代码为例,生成相应的makefile:
Step 1. autoscan 生成 configure.scan
# -*- Autoconf -*-
# 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([weather_log.h])
AC_CONFIG_HEADERS([config.h])
AM_INIT_AUTOMAKE(test,1.0) //这里是需要自己添加的,与AC_INIT内容相似,可自定义
# Checks for programs.
AC_PROG_CXX
AC_PROG_CC
# Checks for libraries.
# FIXME: Replace `main' with a function in `-levent':
AC_CHECK_LIB([event], [-levent])
# FIXME: Replace `main' with a function in `-ljsoncpp':
AC_CHECK_LIB([jsoncpp], [-ljsoncpp])
# FIXME: Replace `main' with a function in `-llog4cplus':
AC_CHECK_LIB([log4cplus], [-llog4cplus])
# FIXME: Replace `main' with a function in `-lmemcached':
AC_CHECK_LIB([memcached], [lmemcached])
# FIXME: Replace `main' with a function in `-lmysqlclient':
AC_CHECK_LIB([mysqlclient], [-lmysqlclient])
# FIXME: Replace `main' with a function in `-lpthread':
AC_CHECK_LIB([pthread], [lpthread])
# FIXME: Replace `main' with a function in `-lrt':
AC_CHECK_LIB([rt], [-lrt])
# Checks for header files.
AC_CHECK_HEADERS([malloc.h stdlib.h string.h unistd.h wchar.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_HEADER_STDBOOL
AC_C_INLINE
AC_TYPE_INT32_T
AC_TYPE_SIZE_T
AC_TYPE_UINT32_T
# Checks for library functions.
AC_FUNC_ERROR_AT_LINE
AC_FUNC_MALLOC
AC_FUNC_MKTIME
AC_FUNC_STRTOD
AC_CHECK_FUNCS([bzero gettimeofday memmove memset strerror strtol])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
这个文件基本不需要我们参与,这里就不贴了
Step 3. autoconf生成configure文件
这个文件我没有用到过,所以也不贴了。。。
到这里,流程图中一条分支就已经完成了,下面我们开始完成另一条分支。
Step 4. Makefile.am的编写
AUTOMAKE_OPTIONs = foreign // 软件等级,foreign、gnu、gnits,默认为gnu
bin_PROGRAMS = test // 可执行文件名,若这里有多个,可以用空格隔开
test_SOURCES = convert_utf.c convert_utf.h simple_ini.h weather_application.cpp weather_application.h weather_configure.cpp weather_configure.h weather_log.cpp weather_log.h weather_main.cpp weather_memclient.cpp weather_memclient.h weather_mysql.cpp weather_mysql.h weather_query_now.cpp weather_query_now.h //这里必须把所有用到的文件都写进来
INCLUDES = -I /data/publiclib/libmemcached/include -I/usr/local/mysql-old/include/mysql/ -I/data/publiclib/libevent/include/ -I/data/publiclib/jsoncpp/include -I/data/publiclib/log4cplus/include/ //头文件所在目录
test_LDADD = -L/data/publiclib/libmemcached/liba -L/data/publiclib/log4cplus/lib -L/data/publiclib/jsoncpp/liba -L/usr/lib64/mysql/ -L/data/publiclib/libevent/liba //依赖库检索路径
LIBS = -levent -llog4cplus -lmemcached -lmysqlclient -ljsoncpp -lrt -lpthread -std=c++98 //依赖库,也可以通过configure.in中的AC_CHECK_LIB实现
每个变量的含义请大家参照上面的注释。
Step 5. autoheader 生成 config.h.in
没有这一步下面会报错
Step 6. automake生成Makefile.in
这里需要注意的是,执行automake 要加参数 --add-missing,这里会为你生成很多文件,最重要的当然是Makefile.in
Step 7. 执行./configure && make && make install
到这里我们的程序就编译成功了,你会发现一个可执行文件test
4.Makefile.am的编写
从上面我们可以看出,整个过程中需要我们参与的基本就是一个Makefile.am的编写,下面这篇文章个人觉得写得挺好的,像我一样的伸手党可以看一下,我就不复制粘贴了:
http://www.ibm.com/developerworks/cn/linux/l-makefile/