Autotools基础使用

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/pengfei240/article/details/78652598

0. 前言

当前开源项目的标准编译过程已经变成了简单的三部曲:configure/make/make install,使用起来很方便。维护者不在需要考虑不同编译环境的问题,也基本上不需要写太多复杂的Makefile。但是,autotools的工具数量太多,涉及的语言也不少,不可能从头学到尾。

本文以一个完整的例子,一步步建立了一个基本可用的模板工程。后续项目可以直接使用该工程,并且可以逐步完善自己的需求。

1. 工具介绍

  • autoscan: 用来扫描源代码目录生成[configure.scan]文件。
  • aclocal: 根据configure.in文件的内容,自动生成[aclocal.m4]文件。
  • autoheader: 扫描configure.ac中的内容,并确定需要如何生成[config.h.in]。
  • autoconf: 在编译软件包前执行一系列测试,发现系统的特性,使源码可以去适应不同系统的差别,增强可移植性。
  • automake: 根据[Makefile.am]自动构建[Makefile.in]的工具。极大地简化了描述软件包结构及追踪源码间依赖关系的过程。
  • Libtool: 是编译器和链接器的命令行接口,利用它可以方便地产生具有可移植性的静态库和动态链接库。

2. 操作流程

Autotools_Sequence

  1. 调用autoscan脚本,生成[configure.scan]文件,并将该文件重命名为[configure.ac]。
  2. 修改[configure.ac],配置项目需要的各种自动化探测项。
  3. 编写自定义宏,为每个宏提供一个单独的*.m4文件。
  4. 调用aclocal收集[configure.ac]中用到的各种非autoconf的宏,包括自定义宏。
  5. 调用autoheader,扫描[configure.ac]、[acconfig.h],生成默认的[config.h.in]宏定义文件。具体文件名称可以在AC_CONFIG_HEADERS中配置。
  6. 编写[Makefile.am]文件,配置编译目标及其源码组成。
  7. 如果[configure.ac]配置了AC_PROG_LIBTOOL或LT_INIT,需要执行libtoolize –automake –copy –force。
  8. 调用automake –add-miss,将每个Makefile.am转化成[Makefile.in]。
  9. 调用autoconf,利用M4解析[configure.ac],生成configure脚本。

基本上只需要修改红色表示的三个步骤就可以配置好工程,基础例子可以参见:

Basic Project

3. 常用宏

AC_PREREQ

原型:AC_PREREQ(VERSION)
功能:需要的最低autoconf版本

AC_PREREQ([2.65])

AC_INIT

原型:AC_INIT(PACKAGE, VERSION, BUG-REPORT-ADDRESS)
功能:autoconf初始化。告诉autoconf包名称,版本,报告bug的Email

AM_INIT_AUTOMAKE

原型:AM_INIT_AUTOMAKE([OPTIONS…])
功能:初始化automake
参数:

参数 描述
-Wall 打开全部警告
-Werror 将警告当错误处理
-foreign 放宽一些GNU标准需求
-1.11.1 需要automake的最低版本
-dist-bzip2 在使用make dist和make distcheck期间同时创建tar.bz2存档
-tar-ustar 使用ustar格式创建tar存档
AM_INIT_AUTOMAKE([foreign -Wall -Werror])

AC_CHECK_HEADERS 或 AC_CHECK_HEADER

原型:
AC_CHECK_HEADERS(HEADERS…)
AC_CHECK_HEADER(HEADER, [ACT-IF-FOUND], [ACT-IF-NOT])
功能:检查头文件。代码中可以使用HAVE_XXX_H的方式检查该头文件是否存在

# 配置文件中的定义
AC_CHECK_HEADERS([string.h])

# 代码中的定义
#if HAVE_STRING_H
#include <string.h>
#else
/* replace header file */
#endif

AC_CONFIG_SRCDIR

原型:AC_CONFIG_SRCDIR ( unique-file-in-source-dir )
功能:确认某些关键文件在正确的目录中

AC_CONFIG_HEADERS

原型:AC_CONFIG_HEADERS(HEADERS…)
功能:创建头文件

# 创建config.h
AC_CONFIG_HEADERS([config.h])

# 创建config.h, 它的输入文件是config.h.ini, 在autoheader时被创建
AC_CONFIG_HEADERS([config.h:config.h.ini])

AC_CHECK_PROGS

原型:AC_CHECK_PROGS (variable, progs-to-check-for, [ value-if-not-found ], [ path = ‘$PATH’])
功能:将variable定义为第一个发现的程序,如果没有发现就设置为VAL-IF-NOT-FOUND

# 如果发现tar,gtar,就设置到变量$TAR中,如果没有发现就设置为‘:’
AC_CHECK_PROGS([TAR], [tar gtar], [:])
if test "$TAR" = :; then
AC_MSG_ERROR([This package needs tar])
fi

AC_DEFINE

原型:AC_DEFINE(VARIABLE, VALUE, DESCRIPTION)
功能:定义一个宏并输出到config.h中
注意:该宏是用于生成C语言的宏。如果value是一个shell变量可以使用AC_DEFINE_UNQUOTED

AC_SUBST

原型:AC_SUBST(VARIABLE, [VALUE])
功能:定义一个宏到Makefile中,可以在Makefile.am中以@XXX@的形式使用

AC_CHECK_LIB

原型:AC_CHECK_LIB(LIBRARY, FUNCT, [ACT-IF-FOUND], [ACT-IF-NOT])
功能:检查库是否存在并且包括函数FUNCT

AC_CHECK_LIB([efence], [malloc], [EFENCELIB=-lefence])
AC_SUBST([EFENCELIB])

AM_CONDITIONAL

原型:AM_CONDITIONAL(NAME, CONDITION)
功能:执行CONDITION中的shell语句,如果成功则定义变量NAME

# 仅当系统中存在bar.h文件时定义WANT_BAR
AC_CHECK_HEADER([bar.h], [use_bar=yes])
AM_CONDITIONAL([WANT_BAR], [test "$use_bar" = yes])

编译器和工具检查

功能
AC_PROG_CC 检查C编译器
AC_PROG_CPP 检查C++编译器
AC_PROG_INSTALL 检查install工具
LT_INIT 检查libtool
AC_PROG_SED 检查sed工具
AC_PROG_YACC 检查YACC工具
AC_PROG_LEX 检查LEX工具

错误处理

功能
AC_MSG_ERROR 打印错误信息并退出
AC_MSG_WARN 打印错误信息但不退出

4. 编写Makefile.am文件

父目录

使用SUBDIRS = XXX的格式增加子目录。

子目录

在autotools中,编译和安装的规则是在一起的:安装目录_编译类型=编译目标

安装目录

安装目录 Makefile中的变量 使用方式
prefix 默认/usr/local 通过–prefix指定
exec_prefix ${prefix} 同prefix
bindir ${exec_prefix}/bin bin_编译类型
libdir ${exec_prefix}/lib lib_编译类型
includedir ${prefix}/include include_编译类型
noinstdir 不安装

- 设置编译目标时需要去掉dir后缀
- 如果自定义一个安装目录时需要加上dir的后缀

编译类型

编译类型 说明 使用方式
PROGRAMS 可执行程序 bin_PROGRAMS
LIBRARIES 库文件 lib_LIBRARIES
LTLIBRARIES libtool库文件 lib_LTLIBRARIES
HEADERS 头文件 include_HEADERS
SCRIPTS 脚本文件 script_SCRIPTS
DATA 数据文件 conf_DATA

- script_SCRIPTS和conf_DATA中的安装目录需要手动配置

编译目标

参数 含义
_SOURCES 源代码文件
_LIBADD 需要链接的库
_LDADD 需要链接的库
_LDFLAGS 对应-L, -l, -shared, -fpic等选项
_LIBTOOLFLAGS libtool编译时的选项

- 编译选项也可以使用宏AM_CFLAGS进行配置
- 如果你的编译目标为lib时,需要使用_LIBADD
- 如果你的编译目标为bin时,需要使用_LDADD

5. 进阶

安装配置文件

某些时候,我们需要将一些配置文件安装到特殊的位置,可以使用下面的方式:

# 定义一个编译目标,安装目录为conf,编译类型为数据文件
confdir = ${exec_prefix}/conf
conf_DATA = utils.conf

详细的例子可以参见:

install config file

打包

缺省情况下打包内容如下:

  • 所有源文件。
  • 所有[Makefile.am]/[Makefile.in]。
  • configure需要读取的文件。
  • [Makefile.am]和[configure.ac]包含的文件。
  • 缺省文件,如README,ChangeLog,NEWS,AUTHORS。

如果需要打包其它文件(包括一些库,特殊的头文件,配置文件,帮助文件),需要特殊指定:

  1. 使用EXTRA_DIST来指定。
  2. 在编译目标前添加dist或nodist前缀。

详细的例子可以参见:

make dist

为configure定义特殊接口

  1. 使用AC_ARG_WITH,添加–with-package参数
  2. 使用AC_ARG_ENABLE,添加-–enable-feature参数

详细的例子可以参见:

Add New Optional Features

根据配置编译不同模块

  1. 使用AC_DEFINE或AC_DEFINE_UNQUOTED定义C语言使用的宏
  2. 使用AM_CONDITIONAL或AC_SUBST定义Makefile使用的宏

详细的例子可以参见:

conditional compilation

配置特殊宏

  1. 新建一个单独的目录,用于存放自定义宏,一般定义为m4
  2. 为每个宏定义一个文件,以.m4结尾
  3. 使用AC_DEFUN定义具体的宏
  4. 运行aclocal -Im4生成aclocal.m4
  5. 在根目录下的Makefile.am中添加ACLOCAL_AMFLAGS = -I m4

详细的例子可以参见:

Add m4 macro

猜你喜欢

转载自blog.csdn.net/pengfei240/article/details/78652598