Makefile 自动生成 - 渣滓

Configure.ac 文件解析

原理:Autoconf 是用来产生 “configure” 文档的工具。“configure” 是一个 shell script,它可以自动设定原始程序以符合各种不同平台上 Unix 系统的特性,并且根据系统参数及环境产生合适的 Makefile 文档或是 C 的标头档 (header file),让原始程序可以很方便地在这些不同的平台上被编译出来。Autoconf 会读取 configure.in configure.ac 档然后产生 “configure” 这个 shell script。

configure.in configure.ac 文档的内容是一连串 GNU m4 的巨集,这些巨集经过 autoconf 处理后会变成检查系统特征的 shell script。configure.in configure.ac 内巨集的顺序并没有特别的规定,但是每一个 configure.in configure.ac 档必须在所有巨集前加入 AC_INIT 巨集,然後在所有巨集的最后面加上 AC_OUTPUT 巨集。

一般先用 autoscan 这个工具扫描原始文件以产生一个 configure.scan 文件,再对 configure.scan 作些修改,从而生成 configure.in configure.ac 文件。

先来看一下 confiugre.scan 文件:

configure.scan 文件

部分宏的意义如下:

  • AC_PREREQ 宏:声明本文件要求的 autoconf 版本,这里使用的是 2.63
  • AC_INIT 宏:用来定义软件的名称和版本等信息,BUG-REPORT-ADDRESS,一般为作者的 E-mail。
  • AC_CONFIG_SRCDIR 宏:用来检测指定的源文件是否存在,来确定源码目录的有效性,在此处为当前目录下的 hello.c。如果有多个源文件,按其默认或只写文件中的任意一个就好了,只是测试。也可以全写上,但文件很多时,完全没有必要。
  • AC_CONFIG_HEADERS 宏:用于生成 config.h 文件,以便 autoheader 使用。【怀疑这个解释的准确性?实际中并未生成。实际效果此条宏影响的是 automake 指令,AC_CONFIG_SRCDIR 用于检测源代码目录下的 config.h 文件。AC_CONFIG_HEADER 表示你想要使用一个配置头文件。】
  • AC_CONFIG_FILES 宏:用于生成相应的 Makefile 文件。【和 AC_OUTPUT(Makefile) 效果相同?】
1
2
3
4
5
6
7
8
#方式一
AC_OUTPUT(Makefile head/Makefile)

#方式二
AC_CONFIG_FILES(Makefile head/Makefile)
AC_OUTPUT

#上述两种书写方式效果一致?后者更规范,理由如下

经过实际测试验证,当前目录或其子目录存在 Makefile.am 或/和 Makefile.in 文件时,autoscan 命令生成 configure.scan 包含 AC_CONFIG_FILES(Makefile1 Makefile2 …);否则,无此宏。
如图,autoscan 自动生成 .scan 文件内容:

configure.scan 文件

所以,更有效/规范的操作顺序是,创建 Makefile.am 文件应该早于执行 autoscan 命令!

——这个地方真的花费了一些时间才整明白,因为网上看到的所有资料要么说 AC_CONFIG_FILES 宏是手动添加的,要么就是按照这篇笔记之前描述的操作顺序,可是配的图片却包含此宏(可实际是不可能的,如果在新添 Makefile.am 文件之前执行 autoscan 命令,生成的 configure.scan 不可能有这条宏)。简单来说,跟着网上的帖子学可以达到生成 makefile,执行 make 的目的,但是真心太粗糙了。

每个 configure.scan 文件都是以 AC_INIT 开头,以 AC_OUTPUT 结束。从文件中的注释可以看出 confiugre.in 文件的一般布局:

1
2
3
4
5
6
7
8
9
10
AC_INIT
测试程序
测试函数库
测试头文件
测试类型定义
测试结构
测试编译器特性
测试库函数
测试系统调用
AC_OUTPUT

上面的调用次序只是建议性质的,但还是强烈建议不要随意改变对宏调用的次序。

configure.in configure.ac 文件中一些宏的含义如下:

#或dnl #或dnl后面的内容作为注释不会被处理,它们是注释的起始标志
AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS])
AM_INIT_AUTOMAKE(PACKAGE,VERSION) 这个是后面运行 automake 命令所必需的宏,PACKAGE 指明要产生软件的名称,VERSION 是其版本号
AC_PROG_CC 检查系统可用的 C 编译器,若源代码是用 C 语言编写的就需要这个宏
AC_OUTPUT(FILE) 设置 configure 命令所要产生的文件。我们最终期望产生 Makefile 这个文件,因此一般将其设置为 AC_OUTPUT(Makefile)

AM_INIT_AUTOMAK E宏:需要自己增加,它是 automake 所必备的宏,其参数与 AC_INIT 宏的参数一样,分别是软件名称和版本编号。

【是需要描述一下 aclocal 命令,但感觉应该是由 autoconf 引出,不该是 automake 啊】

在运行 automak e命令时,还需要一些其他的宏,这些额外的宏由 aclocal 产生。执行 aclocal 会产生 aclocal.m4 文件,如果没有特别的要求,无需修改它。用 aclocal 产生的宏将会提示 automake 如何动作。

另一个重要的文件是 Makefile.am。automake 根据 configure.in 中的宏并在 perl 的帮助下把 Makefile.am 转成 Makefile.in 文件。Makefile.am 文件定义所要产生的目标。

实战 Makefile.am

Makefile.am 是一种比 Makefile 更高层次的规则。只需指定要生成什么目标,它由什么源文件生成,要安装到什么目录等构成。

一般情况是在最上层目录下写一个 Makefile.am,然后在每一个子目录下分别写一个 Makefile.am 文件。automake 会从最上层开始递归处理各个 Makefile.am,每个 Makefile.am 相应生成一个 Makefile.in。

bin_PROGRAMS 定义要产生的可执行文件名,如果要产生多个执行文件,每个文件名用空格隔开。

main_SOURCES 定义“main”这个执行程序所需要的原始文件,如果“ main”这个程序是由多个原始文件所产生的,则必须把它所用到的所有原始文件都列出来,并用空格隔开。要注意的是,如果要定义多个执行文件,则对每个执行程序都要定义相应的 file_SOURCES。

下表列出了可执行文件、静态库、头文件和数据文件,四种书写Makefile.am文件个一般格式。

Makefile.am 一般格式

对于可执行文件和静态库类型,如果只想编译,不想安装到系统中,可以用 noinst_PROGRAMS 代替 bin_PROGRAMS,noinst_LIBRARIES 代替 lib_LIBRARIES。

Makefile.am 还提供了一些全局变量供所有的目标体使用:(目标体是啥?没说明白啊)

Makefile.am 中可用的全局变量

整理此节笔记参考:例解 autoconf 和 automake 生成 Makefile 文件