Linux autotools使用简介
GNU里的强大工具还真是不少,本文将主要关注于GNU Autotools,包括:autoconf, automake等。简要阐述一下如何利用这些工具的强大功能来为linux下的软件开发服务。在linux系统上,有人将autoconf,automake视为与gcc同等重要。
1 概念
首先说明一下什么是GNU Autotools(autoconf, automake, libtool)。
autoconf是一个用于生成可以自动地配置软件源码包,用以适应多种UNIX类系统的shell脚本工具,其中autoconf需要用到m4,便于生成脚本。
automake是一个从Makefile.am文件自动生成Makefile.in的工具。为了生成Makefile.in,automake还需用到perl,由于automake创建的发布完全遵循GNU标准,所以在创建中不需要perl。libtool是一款方便生成各种程序库的工具。
直观上来说,autoconf实现工程配置,automake自动生成工程的Makefile,而且这种makefile是层次式的。
目前automake支持三种目录层次:flat、shallow和deep:
flat指的是所有文件都位于同一个目录中。就是所有源文件、头文件以及其他库文件都位于当前目录中,且没有子目录。我们在开发简单的应用的时候,应该多数都属于这一类;
shallow指的是主要的源代码都储存在顶层目录,其他各个部分则储存在子目录中。就是主要源文件在当前目录中,而其它一些实现各部分功能的源文件位于各自不同的目录。gcc中就有类似的目录层次,而且automake本身就是这一类。
deep指的是所有源代码都被储存在子目录中;顶层目录主要包含配置信息。就是所有源文件及自己写的头文件位于当前目录的一个子目录中,而当前目录里没有任何源文件。 GNU cpio和GNU tar就是这一类。
此外,关于以上工具的详细介绍以及使用方法可以参考下面这本书:http://www.freesoftwaremagazine.com/books/autotools_a_guide_to_autoconf_automake_libtool,如果习惯于看中文材料的话,也可以参考IBM的内部文档:http://www.ibm.com/developerworks/cn/linux/l-makefile/。这篇文章以一个示例工程出发较为详细的阐述了如何使用以上GNU的工具为其生成配置文件以及Makefile,本文的部分图例也是引自该文。本文将以一个更为简单的例子出发,简要叙述一下使用上述工具的流程。
2 示例
我们新建一个简单的工程,命名为“simple”,该工程的层次结构采用deep的方式:
在simple中包含子目录src,用于存储所有的源文件
src目录又包含子目录:include(用于存放公用头文件),core(核心部分源文件),lib(
存放用于生成静态链接库的源文件),lib_so(存放用于生成动态链接库的源文件)
所以需要创建Makefile.am的源文件目录包括:core, lib, lib_so
3 基本流程:
流程图:
autoconf-automake
实例:
1)在当前目录"simple"下运行autoscan命令:将会扫描当前工程内的源文件信息,生成文件configure.scan
2)将configure.scan 文件重命名为configure.in,并修改configure.in文件:
configure.in内的基本结构如下,有<--标记的为在本实例中需要修改的参数:
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.59)
AC_INIT(simple_ccm, 0.1, cmchen@126.com) <-- 初始化配置信息
AC_CONFIG_SRCDIR([src/core/ccm.c])
AC_CONFIG_HEADER([config.h])
AM_INIT_AUTOMAKE(ccm, 0.1) <-- 新添加的与automake相关的参数
dnl Checking for compiler llvmc
# Checks for programs. # 检查编译器
AC_PROG_CC <-- 可以在此处指定默认的编译器
# Checks for libraries. # 检查库
AC_CHECK_LIB([pthread],[pthread_create]) <-- 指定需要检查的库以及库函数
AC_PROG_RANLIB <-- 指定检查ranlib
# Checks for header files. #检查系统头文件
AC_HEADER_STDC
AC_CHECK_HEADERS([stdlib.h])
# Checks for typedefs, structures, and compiler characteristics. #检查类型定义,数据结构以及编译器的一些特征
# Checks for library functions. #检查库函数
AC_OUTPUT([ #configure的输出
Makefile <-- 标注出当前工程中所有需要生成Makefile的子目录
src/core/Makefile
src/lib/Makefile
src/lib_so/Makefile
])
3)在simple目录下新建Makefile.am文件,并在src/core, src/lib, src/lib_so目录下也新建makefile.am文件
首先修改simple目录下的Makefile.am,内容如下:
SUBDIRS=src/lib src/lib_so src/core # 标注当前工程中有源文件需要编译的子目录
CURRENTPATH=$(shell /bin/pwd) # 得到当前路径
INCLUDES=-I$(CURRENTPATH)/src/include # 预先定义编译时包含头文件的路径,并export到子目录
export INCLUDES
修改个分目录下的Makefile.am,这里需要注意的是,三个分目录分别生成不同类型的文件:
src/core中生成可执行文件,Makefile.am内容如下:
bin_PROGRAMS=ccm #指定可执行文件名
ccm_SOURCES=ccm.c xxx.c xxx1.c #生成可执行文件依赖的源文件
#AM_LDFLAGS = -L $(top_srcdir)/src/lib
ccm_LDADD = $(top_srcdir)/src/lib/libccm.a $(top_srcdir)/src/lib_so/libccm.so # 编译链接时需要的库文件
DEFS += -D_GNU_SOURCE
LIBS = -lpthread #指定要链接的库,此信息也可以在configure.in的AC_CHECK_LIB参数中指定
上述的$(top_srcdir)指的是simple目录,bin_PROGRAMS表明是生成可安装的可执行文件,也可以修改前缀用noinst_PROGRAMS表明不安装。
----------------------------------------
src/lib中生成静态链接库,Makefile.am内容如下:
noinst_LIBRARIES=libccm.a #指定生成不安装的静态链接库,同时指定库名称
libccm_a_SOURCES = warn.c decl.c #指定生成该链接库依赖的源文件列表
INCLUDES = -I$(top_srcdir)/src/include
-----------------------------------------
src/lib_so中生成动态链接库,Makefile.am内容如下:
noinst_PROGRAMS = libccm.so #指定生成不安装的动态链接库,同时指定库名称
libccm_so_SOURCES = mesg.c #指定生成该链接库依赖的源文件列表
libccm_so_LDFLAGS = -fPIC -shared
LIBS = -lm
----------------------------------------
4)在simple目录下新建NEWS、 README、 ChangeLog 、AUTHORS文件
5)将/usr/share/automake-1.X/目录下的depcomp和complie文件拷贝到simple目录下
6)运行aclocal命令
7)运行autoconf命令
8)运行automake -a命令
9)运行./confiugre脚本
或者也可以将第6到第9项命令封装到一个脚本文件autogen.sh中批量执行。
4 总结
以上简单阐述了一下autoconf以及automake的使用方法以及为一个工程进行配置和自动生成makefile的流程,libtool的使用未在此文中列出,这部分内容还待补充。总体来说,autotool的使用方便了程序员在linux系统上的开发流程:一方面,它使得程序员可以简捷方便的对一个工程总揽全局,Makefile.am提供了比makefile更加高层的抽象和更强大的功能,程序员不需要痛苦地在每一个分目录下去编写复杂的Makefile; 另一方面,它使得对一个工程的维护也更加方便,如果在当前工程中新添加一个模块,只需要修改工程目录下的configure.in和Makefile.am,以及新模块目录下的Makefile.am即可将新模块集成到工程中。
GNU里的强大工具还真是不少,本文将主要关注于GNU Autotools,包括:autoconf, automake等。简要阐述一下如何利用这些工具的强大功能来为linux下的软件开发服务。在linux系统上,有人将autoconf,automake视为与gcc同等重要。
1 概念
首先说明一下什么是GNU Autotools(autoconf, automake, libtool)。
autoconf是一个用于生成可以自动地配置软件源码包,用以适应多种UNIX类系统的shell脚本工具,其中autoconf需要用到m4,便于生成脚本。
automake是一个从Makefile.am文件自动生成Makefile.in的工具。为了生成Makefile.in,automake还需用到perl,由于automake创建的发布完全遵循GNU标准,所以在创建中不需要perl。libtool是一款方便生成各种程序库的工具。
直观上来说,autoconf实现工程配置,automake自动生成工程的Makefile,而且这种makefile是层次式的。
目前automake支持三种目录层次:flat、shallow和deep:
flat指的是所有文件都位于同一个目录中。就是所有源文件、头文件以及其他库文件都位于当前目录中,且没有子目录。我们在开发简单的应用的时候,应该多数都属于这一类;
shallow指的是主要的源代码都储存在顶层目录,其他各个部分则储存在子目录中。就是主要源文件在当前目录中,而其它一些实现各部分功能的源文件位于各自不同的目录。gcc中就有类似的目录层次,而且automake本身就是这一类。
deep指的是所有源代码都被储存在子目录中;顶层目录主要包含配置信息。就是所有源文件及自己写的头文件位于当前目录的一个子目录中,而当前目录里没有任何源文件。 GNU cpio和GNU tar就是这一类。
此外,关于以上工具的详细介绍以及使用方法可以参考下面这本书:http://www.freesoftwaremagazine.com/books/autotools_a_guide_to_autoconf_automake_libtool,如果习惯于看中文材料的话,也可以参考IBM的内部文档:http://www.ibm.com/developerworks/cn/linux/l-makefile/。这篇文章以一个示例工程出发较为详细的阐述了如何使用以上GNU的工具为其生成配置文件以及Makefile,本文的部分图例也是引自该文。本文将以一个更为简单的例子出发,简要叙述一下使用上述工具的流程。
2 示例
我们新建一个简单的工程,命名为“simple”,该工程的层次结构采用deep的方式:
在simple中包含子目录src,用于存储所有的源文件
src目录又包含子目录:include(用于存放公用头文件),core(核心部分源文件),lib(
存放用于生成静态链接库的源文件),lib_so(存放用于生成动态链接库的源文件)
所以需要创建Makefile.am的源文件目录包括:core, lib, lib_so
3 基本流程:
流程图:
autoconf-automake
实例:
1)在当前目录"simple"下运行autoscan命令:将会扫描当前工程内的源文件信息,生成文件configure.scan
2)将configure.scan 文件重命名为configure.in,并修改configure.in文件:
configure.in内的基本结构如下,有<--标记的为在本实例中需要修改的参数:
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.59)
AC_INIT(simple_ccm, 0.1, cmchen@126.com) <-- 初始化配置信息
AC_CONFIG_SRCDIR([src/core/ccm.c])
AC_CONFIG_HEADER([config.h])
AM_INIT_AUTOMAKE(ccm, 0.1) <-- 新添加的与automake相关的参数
dnl Checking for compiler llvmc
# Checks for programs. # 检查编译器
AC_PROG_CC <-- 可以在此处指定默认的编译器
# Checks for libraries. # 检查库
AC_CHECK_LIB([pthread],[pthread_create]) <-- 指定需要检查的库以及库函数
AC_PROG_RANLIB <-- 指定检查ranlib
# Checks for header files. #检查系统头文件
AC_HEADER_STDC
AC_CHECK_HEADERS([stdlib.h])
# Checks for typedefs, structures, and compiler characteristics. #检查类型定义,数据结构以及编译器的一些特征
# Checks for library functions. #检查库函数
AC_OUTPUT([ #configure的输出
Makefile <-- 标注出当前工程中所有需要生成Makefile的子目录
src/core/Makefile
src/lib/Makefile
src/lib_so/Makefile
])
3)在simple目录下新建Makefile.am文件,并在src/core, src/lib, src/lib_so目录下也新建makefile.am文件
首先修改simple目录下的Makefile.am,内容如下:
SUBDIRS=src/lib src/lib_so src/core # 标注当前工程中有源文件需要编译的子目录
CURRENTPATH=$(shell /bin/pwd) # 得到当前路径
INCLUDES=-I$(CURRENTPATH)/src/include # 预先定义编译时包含头文件的路径,并export到子目录
export INCLUDES
修改个分目录下的Makefile.am,这里需要注意的是,三个分目录分别生成不同类型的文件:
src/core中生成可执行文件,Makefile.am内容如下:
bin_PROGRAMS=ccm #指定可执行文件名
ccm_SOURCES=ccm.c xxx.c xxx1.c #生成可执行文件依赖的源文件
#AM_LDFLAGS = -L $(top_srcdir)/src/lib
ccm_LDADD = $(top_srcdir)/src/lib/libccm.a $(top_srcdir)/src/lib_so/libccm.so # 编译链接时需要的库文件
DEFS += -D_GNU_SOURCE
LIBS = -lpthread #指定要链接的库,此信息也可以在configure.in的AC_CHECK_LIB参数中指定
上述的$(top_srcdir)指的是simple目录,bin_PROGRAMS表明是生成可安装的可执行文件,也可以修改前缀用noinst_PROGRAMS表明不安装。
----------------------------------------
src/lib中生成静态链接库,Makefile.am内容如下:
noinst_LIBRARIES=libccm.a #指定生成不安装的静态链接库,同时指定库名称
libccm_a_SOURCES = warn.c decl.c #指定生成该链接库依赖的源文件列表
INCLUDES = -I$(top_srcdir)/src/include
-----------------------------------------
src/lib_so中生成动态链接库,Makefile.am内容如下:
noinst_PROGRAMS = libccm.so #指定生成不安装的动态链接库,同时指定库名称
libccm_so_SOURCES = mesg.c #指定生成该链接库依赖的源文件列表
libccm_so_LDFLAGS = -fPIC -shared
LIBS = -lm
----------------------------------------
4)在simple目录下新建NEWS、 README、 ChangeLog 、AUTHORS文件
5)将/usr/share/automake-1.X/目录下的depcomp和complie文件拷贝到simple目录下
6)运行aclocal命令
7)运行autoconf命令
8)运行automake -a命令
9)运行./confiugre脚本
或者也可以将第6到第9项命令封装到一个脚本文件autogen.sh中批量执行。
4 总结
以上简单阐述了一下autoconf以及automake的使用方法以及为一个工程进行配置和自动生成makefile的流程,libtool的使用未在此文中列出,这部分内容还待补充。总体来说,autotool的使用方便了程序员在linux系统上的开发流程:一方面,它使得程序员可以简捷方便的对一个工程总揽全局,Makefile.am提供了比makefile更加高层的抽象和更强大的功能,程序员不需要痛苦地在每一个分目录下去编写复杂的Makefile; 另一方面,它使得对一个工程的维护也更加方便,如果在当前工程中新添加一个模块,只需要修改工程目录下的configure.in和Makefile.am,以及新模块目录下的Makefile.am即可将新模块集成到工程中。