学习永无止境!!
分类: 嵌入式
2013-08-14 17:33:59
自动生成Makefile的流程
在进行自动化生成Makefile之前,务必要设定好工作的根目录,在当前环境下,至少要保证autoscan、autoconf、 aclocal、automake这些命令能够正常运行。在这一节中,我们就以一个最简单的示例来说明automake和autoconf的基本使用方 法,这个例子是一个平坦模式的模型。自动生成Makefile的流程如图5-1所示。
(点击查看大图)图5-1 自动生成Makefile的流程 |
在这里使用标准的sntp客户端源代码进行示例,该源代码只有一个源文件和一个头文件,分别是ntp.h和sntp.c。
(1)首先把所有的源代码文件复制到当前的根目录下,然后运行autoscan扫描所有的代码,并得到autoscan.log和configure.scan两个文件。
其中autoscan.log是一个空文件,而configure.scan文件则需要用户手动进行编辑,在该例中,修改之前configure.scan的内容应该如下:
#-*- Autoconf -*- # Process this file with autoconf to produce a configure script. AC_PREREQ(2.57) AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS) AC_CONFIG_SRCDIR([sntp.c]) AC_CONFIG_HEADER([config.h]) # Checks for programs. AC_PROG_CC # Checks for libraries. # Checks for header files. AC_HEADER_STDC AC_CHECK_HEADERS([netdb.h netinet/in.h stdlib.h string.h sys/socket.h sys/time.h unistd.h]) # Checks for typedefs, structures, and compiler characteristics. AC_HEADER_TIME AC_STRUCT_TM # Checks for library functions. AC_FUNC_ERROR_AT_LINE AC_FUNC_MALLOC AC_FUNC_SELECT_ARGTYPES AC_CHECK_FUNCS([bzero gethostbyname gettimeofday select socket strchr]) AC_OUTPUT |
这是一个标准的config模板,后面针对configure文件的修改都是基于这个文件进行的,configure.scan的基本格式如下:
AC_INIT 测试程序 AC_PROG_CC 测试函数库 (在源文件中没有用到函数库) 测试头文件 AC_HEADER_STDC,AC_CHECK_HEADERS 测试类型定义 AC_HEADER_TIME 测试结构 AC_STRUCT_TM 测试编译器特性 测试库函数 AC_FUNC_ERROR_AT_LINE,AC_FUNC_MALLOC AC_FUNC_SELECT_ARGTYPES 测试系统调用 AC_CHECK_FUNCS AC_OUTPUT |
这个文件中有几个非常重要的语句,一般来说所有的configure.scan文件都是以AC_INIT开头和以AC_OUTPUT结束的;而且中 间的顺序一般不要进行随意的改变,因为通常在本列表中靠后的项目依赖于表中靠前的项目。例如,库函数可能受到typedefs和库的影响。
(2)configure.scan文件准备好之后,就开始准备把它改造成自己定制的configure.in文件,先把它的名字修改为configure.in,然后打开该文件进行编辑。在configure.in文件中,必须修改的内容有:
将AC_CONFIG_HEADER([config.h])修改为AM_CONFIG_HEADER([config.h]),也就是说把AC改成AM。
在AM_CONFIG_HEADER下面添加一行AM_INIT_AUTOMAKE(sntp,1.0),这一行命令说明了使用automake最终要得到的结果和版本号。
如果工程中使用了外部的库,比如pthread线程库,在# Checks for libraries这一行的下面还会生成像下面这样的行:
AC_CHECK_LIB([pthread],[pthread_rwlock_init]) |
最后,还要在AC_OUTPUT后面加上要创建的文件名称:AC_OUTPUT([Makefile])。
如果是混合模式或者是深层模式的结构,还需要添加子目录的目标Makefile文件路径到AC_OUTPUT后面的输入中。
此时,configure.in文件的最终内容应该如下:
#-*- Autoconf -*- # Process this file with autoconf to produce a configure script. AC_PREREQ(2.57) AC_INIT(sntp, 1.0, ) AC_CONFIG_SRCDIR([sntp.c]) AM_CONFIG_HEADER([config.h]) AM_INIT_AUTOMAKE(sntp, 1.0) # Checks for programs. AC_PROG_CC # Checks for libraries. # Checks for header files. AC_HEADER_STDC AC_CHECK_HEADERS([netdb.h netinet/in.h stdlib.h string.h sys/socket.h sys/time.h unistd.h]) # Checks for typedefs, structures, and compiler characteristics. AC_HEADER_TIME AC_STRUCT_TM # Checks for library functions. AC_FUNC_ERROR_AT_LINE AC_FUNC_MALLOC AC_FUNC_SELECT_ARGTYPES AC_CHECK_FUNCS([bzero gethostbyname gettimeofday select socket strchr]) AC_OUTPUT |
完成了configure.in文件的编写后,还有一个文件需要用户手动编写,就是Makefile.am文件,针对本工程的一个标准的简易Makefile.am模板如下:
AUTOMAKE_OPTIONS = foreign # Note:target part bin_PROGRAMS = sntp # noinst_PROGRAMS = sntp # Note:source part sntp_SOURCES = sntp.c # sntp_LDADD = # sntp_LDFLAGS = # sntp_DEPENDENCIES = # Note:lib part # lib_LIBRARIES = # sntp_a_SOURCES = # sntp_a_LDADD = # sntp_a_LIBADD = # sntp_a_LDFLAGS = # Note:header part include_HEADERS = ntp.h # Note:data part # data_DATA = |
可以看到Makefile.am文件主要由五个部分组成,分别是目标描述部分、源代码描述部分、库描述部分、头描述部分和数据描述部分。在本例中,由于只有源代码文件和头文件,没有数据和依赖的库,所以对不用的段用井号"#"进行注释。
在目标描述部分,一般有两种选择,如果描述为bin_PROGRAMS,则表明该程序是需要进行安装的,而如果描述为noinst_PROGRAMS,则表明不需要安装。
一般来说,如果不显式地进行声明,默认的几个全局路径如下:
安装路径前缀:$(prefix) = /usr/local
目标文件安装路径:bindir = $(prefix)/bin
库文件安装路径:libdir = $(prefix)/lib
数据文件安装路径:datadir = $(prefix)/share
系统配置安装路径:sysconfdir = $(prefix)/etc
写完了Makefile.am文件之后,生成Makefile的前期准备工作就做完了。接下来就是使用auto系列工具生成的过程,按照如下顺序输入命令:
$./aclocal # 得到aclocal.m4文件 $./autoconf # 得到configure文件 $./automake -a # 得到Makefile.in文件 |
到此为止,就完成了所有自动化的配置任务,把生成的一系列相关文件压缩打包,就可以进行版本的发布了。
用户拿到这个安装包解压后,就可以按照一般软件包的方式进行Makefile的最后生成、编译和安装,也就是输入以下命令:
$ ./configure (得到makefile文件) $ make $ make install |
知识点:使用autoconf和automake来进行自动化配置和生成Makefile的流程可以概括如下:
(1)运行autoscan命令。
(2)将configure.scan文件重命名为configure.in,并修改configure.in文件。
(3)运行aclocal命令得到aclocal.m4文件。
(4)运行autoconf命令得到configure文件。
(5)在工程目录下新建Makefile.am文件,如果存在子目录,子目录中也要创建此文件。
(6)将/usr/share/automake-1.X/目录下的depcomp和compile文件复制到需要处理目录下。
(7)运行automake -a命令得到Makefile.in文件。
(8)运行./configure脚本(这一步已经属于使用自动化管理的范畴了)。