利用autotool生成Makefile
平时自己写的程序多是直接写Makefile,大型的开源C代码,多是通过autotool工具来生成,需要学习下。为了具备通用性,用工作中实际程序来测试。
一 用autoscan生成configure.scan
步骤很简单,解压程序后,在源码目录运行autoscan就会生成configure.scan 如下:
#autoscan
# ll configure.scan
-rw-r--r-- 1 root root 1108 3月 25 20:58 configure.scan
说明:
1、 AC_PREREQQ宏声明本文件要求的autoconf版本,这里是2.69
2、 AC_INIT定义软件的名称和信息。(DULL-PACKAGE-NAME为软件名,VERSION为软件的版本号,BUG-REPORT-ADDRESS为bug的报告地址,一般为软件作者的邮箱)
3、 AC_CONFIG_SRCDIR用来侦测指定的源码文件是否存在,确定源码目录的有效性。此
4、 AC_CONFIG_HEADER用于生成config.h文件,以便autoheader使用
5、 AC_PROG_CC用来指定编译器,以便不指定的时候默认为gcc
6、 AC_OUTPUT用来设定config要产生的文件。如果是Makefile,config会把它检查出来的结果带入Makefile.in文件产生合适的Makefile.
下面需要修改configure.scan 为configure.ac 且修改内容如下:
[root@localhost trunk]# cat configure.ac
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.69])
AC_INIT(flow, 2.6, null)
AM_INIT_AUTOMAKE(flow,2.6)
AC_CONFIG_SRCDIR([aes.c])
AC_CONFIG_HEADERS([config.h])
# Checks for programs.
AC_PROG_CC
# Checks for libraries.
# Checks for libraries.
AC_CHECK_LIB(pthread, pthread_create)
# Checks for header files.
AC_CHECK_HEADERS([arpa/inet.h fcntl.h limits.h locale.h malloc.h netinet/in.h stddef.h stdint.h stdlib.h string.h sys/socket.h sys/time.h unistd.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_CHECK_HEADER_STDBOOL
AC_C_INLINE
AC_TYPE_INT32_T
AC_TYPE_INT64_T
AC_TYPE_PID_T
AC_TYPE_SIZE_T
AC_TYPE_SSIZE_T
AC_TYPE_UINT32_T
AC_TYPE_UINT64_T
AC_TYPE_UINT8_T
AC_CHECK_TYPES([ptrdiff_t])
# Checks for library functions.
AC_FUNC_FORK
AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK
AC_FUNC_MALLOC
AC_FUNC_MKTIME
AC_FUNC_REALLOC
AC_FUNC_STRTOD
AC_CHECK_FUNCS([bzero dup2 gethostname gettimeofday localeconv localtime_r memchr memmove memset mkdir pow regcomp socket strchr strdup strerror strncasecmp strrchr strstr strtol strtoul tzset])
AC_OUTPUT(Makefile etc/Makefile)
1)主要是修改AC_INIT 三个中括号里面内容依次是软件名,版本名,bug报告地址;
2)添加AM_INIT_AUTOMAKE(软件名,版本)
这个宏是必须的,它描述了我们将要生成的软件包的名字及其版本号:PACKAGE是软件包的名字,VERSION是版本号。当你使用make dist命令时,它会给你生成一个类似helloworld-1.0.tar.gz的软件发行包,其中就有对应的软件包的名字和版本号。
- 输出文件名也修改:AC_OUTPUT(Makefile)
二 configure的生成
运行以下命令生成m4宏定义,比如我们使用的AM_INIT_AUTOMAKE,就是用aclocal生成的m4文件里面的:
[root@localhost trunk]# aclocal
如下:
[root@localhost trunk]# ll *.m4
-rw-r--r-- 1 root root 41888 3月 25 21:13 aclocal.m4
运行命令autoconf来生成configure文件:
#autoconf
运行configure文件,报错,缺少Makefile.in无法生成Makefile
三 编写Makefile.am
编写为生成Makefile需要的Makefile.am 文件如下:
AUTOMAKE_OPTIONS=foreign
SUBDIRS=etc
bindir=${prefix}
bin_PROGRAMS=flow
flow_SOURCES=aes.c args.c bloomfilter.c bstrlib.c cJSON.c conf.c deal_flow_file.c file.c flow_deal_main.c ini.c iptool.c list.c log.c mac2.c mac_tool.c
flow_LDFLAGS= -fvisibility=hidden -L/usr/lib64/mysql
AM_CFLAGS= -Wall -O0 -m64 -pg -g -D_REENTRANT -D_THREAD_SAFE -std=gnu99
noinst_HEADERS=aes.h app_context.h args.h Version.h workerid.h
AM_CPPFLAGS=-I/usr/include/mysql
flow_LDADD=-lmysqlclient -lm -lpthread
说明:
- AUTOMAKE_OPTIONS: 设置成foreign会改用一般软件套件标准来检查,默认是gnu模式,automake会检查目录是否存在标准的GNU套件所具备的文档。
- bin_PROGRAMS: 可指定程序名,这里面的bin表示要被安装到系统中,不想安装到系统中,使用noinst_PROGRAMS指定不按照程序到系统中,这里面我们指定程序名。
- flow_SOURCES:生成可执行程序所需要的所有原文件,flow是前面指定的程序名字。
- flow_CPPFLAGS: c预处理器参数,不是CFLAGS(c编译器参数),CXXFLAGS 表示C++编译器参数。
- flow_LDFLAGS: c链接选项
- noinst_HEADERS:不安装到系统中的头文件
- flow_LDADD:链接需要的库
- AM_CFLAGS:C编译选项
四 automake生成Makefile.in
[root@localhost trunk]# automake --add-missing
configure.ac:6: warning: AM_INIT_AUTOMAKE: two- and three-arguments forms are deprecated. For more info, see:
configure.ac:6: https://www.gnu.org/software/automake/manual/automake.html#Modernize-AM_005fINIT_005fAUTOMAKE-invocation
Makefile.am:6: warning: 'INCLUDES' is the old name for 'AM_CPPFLAGS' (or '*_CPPFLAGS')
在Makefile.am 文件中 INCLUDES根据提示用AM_CPPFLAGS替换下。
正常生成Makefile.in之后,用configure 来结合Makefile.in 生成Makefile文件
#通过configure命令后
./configure
[root@localhost trunk]# ll Makefile
-rw-r--r-- 1 root root 37366 3月 26 00:29 Makefile
生成了Makefile文件。
五 编译和安装
make && make install
六 定制安装
刚才默认的安装是安装到/usr/local/下面的,我现在有两个需求:
一是指定安装路径,且不在bin下面,直接在那个目录下面;
二是需要把配置文件拷贝过去,安装后的目录如下;
[root@localhost install-flow]# tree ../install-flow/
../install-flow/
├── etc
│ ├── finger.csv
│ ├── flowDeal.conf
│ ├── mac2org.db
│ ├── MAC_out.log
│ └── mac.sig
└── flow
6.1 更改configure.ac 设置输出
AC_OUTPUT(Makefile etc/Makefile)
原来我们只有一个Makefile,由于配置我们也需要安装,所以增加了配置目录的etc/Makefile的输出。
6.2 制作Makefile.am
更改根目录的Makefile.am 设置下安装目录bindir,且要设置递归调用Makefile子目录SUBDIRS,整体如下:
bindir=${prefix}
SUBDIRS=etc
在配置文件目录etc下新建Makefile.am内容如下:
configdir=${prefix}/etc
config_DATA=finger.csv flowDeal.conf mac2org.db MAC_out.log mac.sig
6.3 重新编译安装
重新生成和编译安装:
#automake --add-missing
#./configure --prefix=/root/flowdeal/install-flow
#make && make install
结果顺利完成编译和安装。
七 梳理 整体步骤
1. autoscan
2. configure.scan ==> configure.in/configure.ac
3. aclocal
4. autoheader(可选,生成config.h.in)
5. Makefile.am(根据源码目录可能需要多个)
6. libtoolize –automake –copy –force(如果configure.ac中使用了libtool)
7. automake –add-missing
8. autoconf
9. ./configure && make && make install
以前画的图:

八 参考
[automake 和 autoconf 使用简明教程](https://thebigdoc.readthedocs.io/en/latest/auto-make-conf.html)
[大型项目使用Automake/Autoconf完成编译配置(2)——步步为营_华仔爱技术的博客-CSDN博客](https://blog.csdn.net/yunhua_lee/article/details/6172617)
[linux 下 automake 使用教程_踏莎行的博客-程序员宅基地 - 程序员宅基地 (cxyzjd.com)](https://www.cxyzjd.com/article/u012234115/45060673)
[https://www.jianshu.com/p/2f5e586c3402](https://www.jianshu.com/p/2f5e586c3402)
[https://www.cnblogs.com/zhangrxiang/p/8366596.html](https://www.cnblogs.com/zhangrxiang/p/8366596.html)