本文将介绍如何在linux(以ubuntu20.04为例)下通过automake、autoconf等命令自动生成Makefile脚本.

1.首先安装依赖的包:

通过命令sudo apt-get install automake autoconf来安装automake和autoconf包.

2.过程图解:

图1 自动生成Makefile脚本的流程图

3.案例分析:

下面以一个简单的C语言程序为例,说明如何自动生成Makefile脚本.测试目录下包含bin,src和obj三个目录,其中src目录下主要包含add.c, div.c, main.c, mul.c,sub.c和common.h等源代码文件,其中的内容如下:

//add.c
int add(int a, int b){
   return a+b;
}
//sub.c
int sub(int a, int b){
     return a-b;
}
//mul.c
int mul(int a, int b){
    return a*b;
}
//div.c
int div(int a, int b){
    return a/b;
}
//common.h
#ifndef _COMMON_H
#define _COMMON_H
extern int add(int a, int b);
extern int sub(int a, int b);
extern int mul(int a, int b);
extern int div(int a, int b);
//main.c
#include<stdio.h>
#include "common.h"
int main(){
   int a=8, b=2;
   printf("a+b=%d\n", add(a,b));
   printf("a-b=%d\n", sub(a,b));
   printf("a*b=%d\n", mul(a,b));
   printf("a/b=%d\n", div(a,b));
   return 0;
}

步骤1:运行autoscan命令生成configure.scan文件

图2 生成configure.scan文件

步骤2:将configure.scan文件名重命名为configure.ac

步骤3:修改configure.ac文件中的内容:

图3 configure.scan原始内容

图4 configure.scan修改后的内容

对修改的条目信息做如下的简要介绍:

  • AC_PREREQ 宏声明本文件要求的autoconf版本,本例使用的版本为2.69。
  • AC_INIT 宏用来定义软件的名称和版本等信息,”FULL-PACKAGE-NAME”为软件包名称,”VERSION”为软件版本号,”BUG-REPORT-ADDRESS”为BUG报告地址(一般为软件作者邮件地址)。(这里只使用第一个参数,指定整个程序main的入口所在源文件)
  • AM_INIT_AUTOMAKE   指定生成的可执行文件(这里为main)
  • AC_CONFIG_SRCDIR 宏用来侦测所指定的源码文件是否存在,来确定源码目录的有效性。(这里不需要检测有效性,所以将其注释掉)
  • AC_CONFIG_HEADER 宏用于生成config.h文件,以便autoheader使用。(这里后期不适应autoheader命令,所以将其注释)
  • AC_PROG_CC 用来指定编译器,如果不指定,选用默认gcc。
  • AC_OUTPUT 用来设定 configure 所要产生的文件,如果是Makefile,configure会把它检查出来的结果带入makefile.in文件产生合适的makefile。使用Automake时,还需要一些其他的参数,这些额外的宏用aclocal工具产生。(这里指定生成的Makefile)

步骤4:运行aclocal命令生成aclocal.m4命令,然后基于aclocal.m4和configure.in两个文件运行autoconf生成configure文件.

图5 生成configure文件

步骤5:手动创建并编辑如下的Makefile.am文件:

图6 创建编辑Makefile.am文件

对Makefile.am中的条目做如下的简要介绍:

  • AUTOMAKE_OPTIONS 为设置automake的选项。由于GNU对自己发布的软件有严格的规范,比如必须附带许可证声明文件COPYING等,否则automake执行时会报错。automake提供了3种软件等级:foreign、gnu和gnits,供用户选择,默认等级为gnu。本例使需用foreign等级,它只检测必须的文件。
  • bin_PROGRAMS 定义要产生的执行文件名。如果要产生多个执行文件,每个文件名用空格开。(本例中产生的可执行文件main)
  • main_SOURCES 定义”main”这个执行程序所需要的原始文件。如果”main”这个程序是由多个原始文件所产生的,则必须把它所用到的所有原始文件都列出来,并用空格隔开。例如:若目标体”main”需要”main.c”、”common.h”两个依赖文件,则定义main_SOURCES=main.c common.h(本例子中所需要的原始文件都在src目录下)
  • clean-generic(可省略)  为后面删除obj目录下和bin目录下的文件做准备(执行make clean命令即可完成删除)
  • install-am(可省略)  为后面移动.o文件和可执行文件main做准备(执行 make install命令即可完成移动文件)

步骤6:执行automake –add-missing命令,产生Makefile.in文件;

步骤7:最后执行./configure命令,自动生成Makefile脚本;

图7 生成Makefile脚本

步骤8:运行make命令,验证Makefile脚本的正确性;

图8 执行Make命令

编译成功后,当前目录下生成.o和main的可执行文件,运行make install命令将.o文件和main可执行文件分别移动到obj目录和bin目录下. 如果想要删除obj和main下的.o和main文件,执行make clean命令即可.

图9 执行make install命令