Linux 下 automake 工具使用 (自动构建 Makefile 文件)
一、前言
linux 环境下,当项目工程很大的时候,编译的过程很复杂,所以需要使用 make 工具,自动进行编译安装,但是手写 makefile 文件比较复杂,所幸在 GNU 的计划中,设计出了一种叫做 Autoconf/Automake 的工具,用来自动生成 makefile 文件,为编译和安装程序提供了一个方便快捷的入口。
无论是在 Linux 还是在 Unix 环境中,make 都是一个非常重要的编译命令。不管是自己进行项目开发还是安装应用软件,我们都经常要用到 make 或 make install。利用 make 工具,我们可以将大型的开发项目分解成为多个更易于管理的模块,对于一个包括几百个源文件的应用程序,使用 make 和 makefile 工具就可以轻而易举的理顺各个源文件之间纷繁复杂的相互关系。
但是如果通过查阅 make 的帮助文档来手工编写 Makefile,对任何程序员都是一场挑战。
下面将介绍如何利用 GNU Autoconf 及 Automake 这两套工具来协助我们自动产生 Makefile 文件,并且让开发出来的软件可以像大多数源码包那样,只需"./configure", "make","make install" 就可以把程序安装到系统中。
目前 automake 支持三种目录层次:flat、shallow 和 deep。
flat 指的是所有文件都位于同一个目录中。
就是所有源文件、头文件以及其他库文件都位于当前目录中,且没有子目录。Termutils 就是这一类。
shallow 指的是主要的源代码都储存在顶层目录,其他各个部分则储存在子目录中。
就是主要源文件在当前目录中,而其它一些实现各部分功能的源文件位于各自不同的目录。automake 本身就是这一类。
deep 指的是所有源代码都被储存在子目录中;顶层目录主要包含配置信息。
就是所有源文件及自己写的头文件位于当前目录的一个子目录中,而当前目录里没有任何源文件。
二、安装 Automake 工具
先检查当前系统里是否安装了工具。
安装成功的提示:
如果系统没有安装 Automake 工具,红帽子系统可以挂载光盘找到安装包进行安装
如果是 ubuntu 系统可以通过命令在线下载工具: sudo apt-get install autoconf automake libtool






三、Automake 工具使用方法

3.1 现在一个目录下,编写好一个 C 代码文

3. 2 执行 autoscan 命令生成 configure.scan 文件
生成 configure.scan 文件之后,将文件修改成 configure.ac 文件,如果没有这个.ac 文件,执行 aclocal 命令的时候会报错。

3.3 修改 configure.ac 文件参数
AC_PROG_RANLIB 如果是多线程的程序的话要加入这句话,要不运行 automake 命令时会出错
每个 configure.ac 文件都是以 AC_INIT 开头,以 AC_OUTPUT 结束。

关键字解释:
AC_INIT()中分别的是: 软件包的名字,版本,作者的联系方式(一般是 Email)
在下面再自己添加一行 AM_INIT_AUTOMAKE(),里面填入: 程序名字,版本号。
最后 AC_OUTPUT()填写生成的文件名称。
(1)AC_PREREQ 宏声明本文件要求的 autoconf 版本,本例使用的版本为 2.63。
(2)AC_INIT 宏用来定义软件的名称和版本等信息,”FULL-PACKAGE-NAME”为软件包名称,”VERSION”为软件版本号,”BUG-REPORT-ADDRESS”为 BUG 报告地址(一般为软件作者邮件地址)。
(3)AC_CONFIG_SRCDIR 宏用来侦测所指定的源码文件是否存在,来确定源码目录的有效性。此处为当前目录下的 app.c。
(4)AC_CONFIG_HEADER 宏用于生成 config.h 文件,以便 autoheader 使用。
(5)AC_PROG_CC 用来指定编译器,如果不指定,选用默认 gcc。 比如: AC_PROG_CC(gcc)
(6)AC_OUTPUT 用来设定 configure 所要产生的文件,如果是 makefile,configure 会把它检查出来的结果带入 makefile.in 文件产生合适的 makefile。使用 Automake 时,还需要一些其他的参数,这些额外的宏用 aclocal 工具产生。

3.4 执行 aclocal 命令生成 aclocal.m4 文件

3.5 使用 autoconf 工具生成 configure 文件

3.6 使用 autoheader 生成 config.h.in 文件

3.7 手工编辑 Makefile.am 文件
Automake 工具会根据 config.in 中的参量把 Makefile.am 转换成 Makefile.in 文件。在使用 Automake 之前,要先手动建立 Makefile.am 文件。
Makefile.am 是一种比 Makefile 更高层次的规则。只需指定要生成什么目标,它由什么源文件生成,要安装到什么目录等构成。

文件创建之后,需要写三项代码:
第一项:软件规范,有三个候选项:foreign(国外),gnu(GNU),gnits
如果使用 foreign 等级,它只检测必须的文件
第二项:生成的可执行文件名
第三项:生成可执行文件所需的原始文件,有多个文件时用空格隔开。
示例:

3.8 使用 automake 命令生成 Makefile.in 文件
添加选项--add-missing 可以让 automake 工具自动添加必要的脚本文件
注意: 不能在共享目录下执行,因为共享目录下是 windows 文件系统(FA32/NTFS),不支持 link 操作。
不然会报以下错误:

示例:

3.9 运行 configure 配置生成最终的 Makefile 文件
configure 脚本为了让一个程序能够在各种不同类型的机器上运行而设计的。在使用 make 编译源代码之前,configure 会根据自己所依赖的库而在目标机器上进行匹配。
约定俗成的,所有的 configure 脚本都把脚本文件名起为 configure,一般来讲都是 shell 脚本,根据所在的系统环境生成 makefile 文件。
configure 脚本运行时扫描当前环境,生成一个名为 config.status 的子脚本。子脚本将 Makefile.in 文件转换为适应于当前系统环境的 Makefile 文件。

3.10 使用 Makefile 编译,运行程序

3.11 Make 支持的其他命令
四、configure 文件详解
五、多个文件生成 Makefile 示例(同级目录)
在目录下有 3 个.c、2 个头文件

configure.ac 文件内容:

Makefile.am 文件内容:

六、Makefile.am 格式详解
6.1 Makefile.am 中可用的全局变量
示例:
6.2 Makefile.am 中可用的路径变量
在 Makefile.am 中尽量使用相对路径,系统预定义了两个基本路径:
automake 标准安装路径
默认安装路径为:$(prefix) = /usr/local,可以通过./configure --prefix=<new_path>的方法来覆盖。
其它的预定义目录还包括:bindir = (prefix)/lib, datadir = (prefix)/etc 等等。
定义一个新的安装路径
比如 test, 可定义 testdir = (prefix)/ /test 目录下。
示例:
6.3 Makefile.am 一般格式 Makefile.am 一般格式
PROGRAMS。表示可执行文件
LIBRARIES。表示静态库文件
LTLIBRARIES。表示动态库文件,前面的 LT 表示 libtool。
HEADERS。头文件。
SCRIPTS。脚本文件,这个可以被用于执行。如:example_SCRIPTS,如果用这样的话,需要我们自己定义安装目录下的 example 目录
DATA。数据文件,不能执行。
对于可执行文件和静态库类型,如果只想编译,不想安装到系统中,可以用 noinst_PROGRAMS 代替 bin_PROGRAMS,noinst_LIBRARIES 代替 lib_LIBRARIES。
如果有帮助文档,不需要编译,但是需要随着软件发布一起发布,可以按下面格式进行定义:
七、auotomake 多级目录生成 Makefile(不发布静态库)
7.1 创建待编译的源码(模拟真实项目环境)
在第一章里简单介绍了使用 automake 自动产生 makefile 的几个关键步骤,所有文件都在同一个目录下。但在比较大的项目中,很少将所有文件放在一个目录下的。下面将针对这种情况做个简单介绍。
多级目录结构的软件,一般是单个程序、库文件或模块放在各自的目录中。automake 要求每个目录都有自己的 Makefile.am 文件来编译各自目录 下的代码。在顶级的目录中,有一个 Makefile.am 文件,该文件通过 SUBDIRS 指明了这个目录下有多少个直接下级目录的代码需要编译。下级目录的 Makefile.am 也指明自己需要编译的下级目录。通过这样的层层递归 i,从而完成多级目录结构的编译。
下面模拟了一个项目工程:

顶层目录是 project,在 project 目录下分别是 main\print\sum 目录。 main 目录里的 main.c 是包含 main 函数的主程序,分别调用了 sum 和 print 目录下.c 文件里的函数。
7.2 project 顶层目录下的操作过程
执行 autoscan 命令生成 configure.scan 文件
在 project 目录下运行 autoscan 命令生成 configure.scan 文件。

将 configure.scan 改名成 configure.in (早期 in 现在常用.ac)
修改 configure.in 文件

分别执行 aclocal、autoconf、autoheader 命令

创建 Makefile.am 文件
编辑内容如下:
如果有帮助文档,不需要编译,但是需要随着软件发布一起发布,可以按下面格式进行定义:
doc/help.txt 不需要编译,但要发布该文件。如果有多个文件,则用空格分开。
7.3 main 目录下创建 Makefile.am 文件
在 main 目录下建立 Makefile.am 文件。
app_LDADD 指定需要的库文件
INCLUDES 指定需要的头文件
7.4 print 目录下创建 Makefile.am 文件
内容:
7.5 sum 目录下创建 Makefile.am 文件
内容:
7.6 编译
八、auotomake 多级目录生成 Makefile(发布静态库)
目录结构如下

在 main.里调用了 led.c 和 key.c 里的函数。
(1) main.c 代码
(2) led.c 和 led.h 代码
(3) key.c 和 key.h 代码

调用关系图
顶层 Makefile.am 文件代码(自己创建)
user/Makefile.am 文件代码(自己创建)
key/Makefile.am 文件代码(自己创建)
led/Makefile.am 文件代码(自己创建)
顶层目录下的 configure.ac 文件代码
执行命令: aclocal\autoconf\autoheader
automake --add-missing
./configure --prefix=$PWD/_install
make && make install
在安装目录下的文件结果

九、auotomake 多级目录生成 Makefile(发布动态库+静态库)
目录结构如下

在 main.里调用了 led.c 和 key.c 里的函数。
在 main.里调用了 led.c 和 key.c 里的函数。
(1) main.c 代码
(2) led.c 和 led.h 代码
(3) key.c 和 key.h 代码

调用关系图
顶层 Makefile.am 文件代码(自己创建)
user/Makefile.am 文件代码(自己创建)

key/Makefile.am 文件代码(自己创建)
led/Makefile.am 文件代码(自己创建)
顶层目录下的 configure.ac 文件代码
执行命令: aclocal\autoconf\autoheader
执行命令: libtoolize -f -c #共享库必须要执行
automake --add-missing
./configure --prefix=$PWD/_install
make && make install
在安装目录下的文件结果

十、自定义安装目录示例(make install)

格式:
wbyq:表示是新的路径类型。
wbyq_666:表示在安装路径下创建的目录名称。
666.c、888.c :是执行 make install 拷贝到 wbyq_666 目录下的文件。
十一、多级目录与函数的嵌套调用生成 Makefile

图 11.1 C 文件的调用关系图
版权声明: 本文为 InfoQ 作者【DS小龙哥】的原创文章。
原文链接:【http://xie.infoq.cn/article/d5ccf2f101e935a73115f30ec】。文章转载请联系作者。
评论