1.1. Autotools相关工具链
1.1.1. Autotools
Autotools是一系列工具
- autoscan
可以通过调用autoscan命令,得到一个初始化的configure.scan文件。然后重命名为configure.ac后,在此基础上编辑configure.ac。
autoscan会扫描源码,并生成一些通用的宏调用,输入的声明,以及输出的声明。尽管autoscan十分方便,但是没人能够在构建之前,就把源码完全写好。
因此,autoscan通常用于初始化configure.ac,即生成configure.ac的雏形文件configure.scan - aclocal
configure.ac实际是依靠宏展开来得到configure。因此,能否成功生成,取决于宏定义是否能够找到。
autoconf会从自身安装路径下寻找事先定义好的宏。然而对于像automake,libtool,gettex等第三方扩展宏,autoconf便无从知晓。
因此,aclocal将在configure.ac同一个目录下生成aclocal.m4,在扫描configure.ac过程中,将第三方扩展和开发者自己编写的宏定义复制进去。
如此一来,autoconf遇到不认识的宏时,就会从aclocal.m4中查找 - autoconf
autoconf是 用来产生configure文件的 .configure是 一个脚本,它能设置源程序来适应各种不同的操作系统平台,并且根据不同的 系统来产生合适的 Makefile,从而可以使你的源代码能在不同的操作系统平台上被编译出来. - autoheader
autoheader命令扫描configure.ac文件,并确定如何生成config.h.in。每当configure.ac变化时,都可以通过执行autoheader更新config.h.in。
在configure.ac通过AC_CONFIG_HEADERS([config.h])告诉autoheader应当生成config.h.in的路径,
config.h包含了大量的宏定义,其中包括软件包的名字等信息,程序可以直接使用这些宏。
更重要的是,程序可以根据其中的对目标平台的可移植相关的宏,通过条件编译,动态的调整编译行为。 - automake
手工编写Makefile是一件相当繁琐的事情,并且随着项目的复杂程序变大,编写难度越来越大。automake工具应运而生。
可以编辑Makefile.am文件,并依靠automake来生成Makefile.in
1.1.2. 其他相关工具
- m4
m4是一个经典的宏工具。autoconf正是构建在m4之上,可以理解为autoconf预先定义了大量的,用户检查系统可移植性的宏,这些宏在展开就是大量的shell脚本。
所以编写configure.ac就需要对这些宏掌握熟练,并且合理调用。 - libtool
libtool试图解决不同平台下,库文件的差异。libtool实际是一个shell脚本,实际工作中,调用了目标平台的cc编译器和链接器,以及给予合适的命令行参数。
libtool可以单独使用,也可以跟autotools集成使用。 - autoreconf
早期autoreconf并不存在,软件开发者就自己编写脚本,按照顺序调用autoconf,autoheader,automake等工具.
autoreconf程序能够自动按照合理的顺序调用autoconf,automake,aclocal程序
1.2. 工具链的流程
1.2.1 autotools完整流程
1.2.2 autoreconf
1.2.3 behind autoreconf
1.2.4 configure生成Makefile
your source files --> [autoscan*] --> [configure.scan] --> configure.ac
[acinclude.m4] --.
|
[local macros] --+--> aclocal* --> aclocal.m4
|
configure.ac ----'
configure.ac --.
| .------> autoconf* -----> configure
[aclocal.m4] --+---+
| `-----> [autoheader*] --> [config.h.in]
[acsite.m4] ---'
configure.ac --.
+--> automake* --> Makefile.in
Makefile.am ---'
.-------------> [config.cache]
configure* --------------+------------> config.log
|
[config.h.in] -. v .-> [config.h] -.
+--> config.status* -+ +--> make*
Makefile.in ---' `-> Makefile ---'
所以需要项目维护者手动修改的文件除了可选的NEWS README AUTHORS ChangeLog文件之外,就是configure.ac文件和每个源码文件夹下的Makefile.am文件了。
- 调用autoscan脚本,生成[configure.scan]文件,并将该文件重命名为[configure.ac]。
- 修改[configure.ac],配置项目需要的各种自动化探测项。
- 编写自定义宏,为每个宏提供一个单独的*.m4文件。
- 调用aclocal收集[configure.ac]中用到的各种非autoconf的宏,包括自定义宏。
- 调用autoheader,扫描[configure.ac]、[acconfig.h],生成默认的[config.h.in]宏定义文件。具体文件名称可以在AC_CONFIG_HEADERS中配置。
- 编写[Makefile.am]文件,配置编译目标及其源码组成。
- 如果[configure.ac]配置了AC_PROG_LIBTOOL或LT_INIT,需要执行libtoolize –automake –copy –force。
- 调用automake –add-miss,将每个Makefile.am转化成[Makefile.in]。
- 调用autoconf,利用M4解析[configure.ac],生成configure脚本。
基本上只需要修改红色表示的三个步骤就可以配置好工程
1.3. autoconf
1.3.1. configure.ac文件
configure.ac用于生成configure脚本,以下以clist工程举例。
例如有以下文件结构
.
├── clist // clist库
│ ├── clist.c
│ ├── clist.h
│ ├── CMakeLists.txt // 该文件是用于cmake的,忽略
│ ├── config.h.in // 该文件是用于cmake的,忽略
│ └── Makefile.am
├── CMakeLists.txt // 该文件是用于cmake的,忽略
├── configure.ac
├── .gitignore // 该文件是用于git的,忽略
├── LICENSE
├── m4
│ └── .gitignore // 该文件是用于git的,忽略
├── Makefile.am
├── README.md
└── samples // 测试程序,需要链接clist库
├── CMakeLists.txt // 该文件是用于cmake的,忽略
├── Makefile.am
├── memcheck.stp // 该文件是用于systemstap的,忽略
└── test.c
其中需要在autotools构建中用到的文件除了源码文件之外,还有./configure.ac
、./Makefile.am
、./clist/Makefile.am
、./samples/Makefile.am
、./m4/
。
m4为空文件夹,是为了后续存放自动生成的m4宏文件避免autoconf告警,由于git无法提交空文件夹,故在其下add了一个.gitignore文件。
使用autoscan扫描目录后,修改自动生成的configure.scan为configure.ac,并修改如下
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.69])
AC_INIT([clist], [1.0.1.1114], [tangm421@outlook.com])
AC_CONFIG_SRCDIR([clist/clist.c])
AC_CONFIG_HEADER(config.h)
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_MACRO_DIR([m4])
#m4_pattern_forbid([^PKG_])
AM_INIT_AUTOMAKE
AM_PROG_AR([AC_MSG_ERROR([cannot find any available compression tool for \$AR])])
AC_DISABLE_SHARED
LT_INIT()
# Checks for programs.
AC_PROG_CC
#AC_DISABLE_SHARED // 这类宏放在LT_INIT之后是无效的
#AC_PROG_INSTALL // 若使用这两个老式宏,AC_PROG_CC最好放在此宏之前,否则会有N多警告
#AC_PROG_LIBTOOL
dnl AC_PROG_RANLIB // 若使用了libtool则需要将AC_PROG_RANLIB去掉,且#注释无效
AC_CANONICAL_HOST
#AC_PROG_MAKE_SET
# Checks for libraries.
# Checks for header files.
#AC_CHECK_HEADERS([malloc.h stdio.h stdlib.h string.h])
# Checks for typedefs, structures, and compiler characteristics.
#AC_CHECK_HEADER_STDBOOL
AC_CHECK_HEADERS([db_cxx.h],
[echo "db_cxx.h found"],
[AC_MSG_WARN([db_cxx.h not found])],
[#ifdef HAVE_FOO_H
# include <inttypes.h>
#endif
])
AC_MSG_NOTICE([Using native OSTYPE value from \$host_os: $host_os, ARCH/LARCH value from \$host_cpu: $host_cpu])
#AC_DEFINE(PROJECT_IMPORTEXPORT, [], [Only usefull for windows])
#AH_TEMPLATE(PROJECT_IMPORTEXPORT, [Only usefull for windows])
AC_DEFINE_UNQUOTED(PROJECT_IMPORTEXPORT, ${PROJECT_IMPORTEXPORT:""}, [Only usefull for windows])
AC_ARG_ENABLE(clist-debug,
[AS_HELP_STRING([--enable-clist-debug], [Enable clist debug print])],
AC_SUBST(LIBCLIST_CPPFLAGS, "-DCLIST_DEBUG"),
AC_SUBST(LIBCLIST_CPPFLAGS, ""))
# Checks for library functions.
#AC_FUNC_MALLOC
AC_CONFIG_FILES([Makefile clist/Makefile samples/Makefile])
AC_OUTPUT
#AC_OUTPUT([Makefile clist/Makefile samples/Makefile])
1.3.2. configure.ac文件的标准布局
configure.ac调用Autoconf宏的顺序并不重要,但有一些例外。每个configure.ac必须在检查之前包含对AC_INIT的调用,并在末尾包含对AC_OUTPUT的调用(参阅Output)。此外,某些宏依赖于首先被调用的其他宏,因为它们会检查某些变量的先前设置值来决定要做什么。这些宏在各个描述中都有说明(参阅Existing Tests),并且如果调用它们的顺序不正确,它们还会在创建配置时向您发出警告。
为了鼓励一致性,以下是建议的调用Autoconf宏的顺序
Autoconf requirements
AC_INIT(package, version, bug-report-address)
information on the package
checks for programs
checks for libraries
checks for header files
checks for types
checks for structures
checks for compiler characteristics
checks for library functions
checks for system services
AC_CONFIG_FILES([file...])
AC_OUTPUT
1.3.3. configure.ac常见宏说明
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
参数:
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])
1.3.5. 常用变量
Autoconf会预设一些输出变量,例如:
1.4. automake
1.4.1. Makefile.am文件
Makefile.am是一种比Makefile更高层次的规则。只需指定要生成什么目标,它由什么源文件生成,要安装到什么目录等构成。
- 原则1:每个目录一个Makefile.am文件;同时在configure.ac的AC_CONFIG_FILES宏中指定输出所有的Makefile文件
- 原则2:父目录需要包含子目录,在父目录下的Makefile.am中添加: SUBDIRS = 子目录
- 原则3:Makefile.am中指明当前目录如何编译
Makefile.am用以生成最终的Makefile编译脚本,以下还是以clist工程为例
./Makefile.am
AUTOMAKE_OPTIONS = foreign
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = clist
SUBDIRS += samples
cmakedatadir = $(datadir)/cmake
nobase_dist_cmakedata_DATA = ./CMakeLists.txt
nobase_dist_cmakedata_DATA += clist/CMakeLists.txt
nobase_dist_cmakedata_DATA += ./samples/CMakeLists.txt
这里我把foreign选项放在了最顶层的Makefile.am中,由于configure.ac文件中加入了AC_CONFIG_MACRO_DIR宏,故此处必须加上ACLOCAL_AMFLAGS = -I m4
。
SUBDIRS是一个特殊变量,列出了在处理当前目录之前应递归到的所有目录。所有在此声明的子目录也参与到构建工程,故也需要Makefile.am文件。
关于此文件中的最后几行则是在执行make install
时将几个cmake文件按照原始文件结构层次安装到$(datadir)/cmake
目录下,并且允许在分发(执行make dist
)时将这几个cmake文件按照层次结构也包含在内。
./clist/Makefile.am
lib_LTLIBRARIES = libclist.la
libclist_la_CPPFLAGS = @LIBCLIST_CPPFLAGS@
libclist_la_SOURCES = config.h clist.c
include_HEADERS = clist.h
子目录clist下用来编译clist库,因为启用了libtool(libtool将共享库和静态库抽象为一个统一的概念,称为libtool库。 libtool库是使用.la后缀的文件,并且可以指定静态库,共享库或两者。在运行./configure之前,无法确定它们的确切性质:并非所有平台都支持所有类型的库,并且用户可以显式选择应构建的库。由于共享库和静态库的目标文件必须以不同的方式进行编译,因此在编译过程中也会使用libtool。 libtool构建的对象文件称为libtool对象:这些文件使用.lo后缀。 Libtool库是从这些libtool对象构建的)所以此处库名为libclist.la,使用libclist_la_为前缀添加预编译指令、源码文件及包含文件。LIBCLIST_CPPFLAGS则是先前的configure.ac文件中声明的一个automake变量在此处引用。
./samples/Makefile.am
#AM_CFLAGS = -I$(top_srcdir)/clist
bin_PROGRAMS = sample
sample_CFLAGS = -I$(top_srcdir)/clist
sample_SOURCES = test.c
sample_LDADD = ../clist/libclist.la
sample_CPPFLAGS = -D_BINDIR='"$(bindir)"'
nodist_sample_SOURCES = mydefines.h
BUILT_SOURCES = mydefines.h
CLEANFILES = mydefines.h
mydefines.h: Makefile
echo '#define INSTALL_BINDIR "$(bindir)"' > $@
子目录samples用来编译测试程序,程序名为sample,使用sample_为前缀添加C编译标志、源码以及链接库。
关于此文件中的最后几行,是为了说明后面如何引用预定义的变量的问题,BUILT_SOURCES
则是为了在构建sample之前生成mydefines.h,关于BUILT_SOURCES
变量的说明参阅automake 9.4 Built Sources
在静态库和动态库同时存在时,libtool默认链接的动态库
1.4.2. 语法说明
1.4.2.1. 统一命名规范
Automake变量通常遵循统一的命名规范,可以轻松决定程序(和其他派生对象)的构建方式以及安装方式。该规范还支持configure
时确定应构建的内容。
在make
时,某些变量用于确定要构建的对象。变量名由几部分组成,这些部分串联在一起,其中指示构建的部分通常称为元
。
1.4.2.2. 元
就拿_PROGRAMS
为例,以_PROGRAMS结尾的变量,列出了生成的Makefile应该生成的程序。用Automake语言来说,此_PROGRAMS后缀称为元
。
bin_PROGRAMS的bin
部分告诉automake应该将生成的程序安装在bindir中。回想一下,GNU Build System使用一组变量来表示目标目录,并允许用户自定义这些位置。任何这样的目录变量都可以放在元
前面(省略dir后缀),以告诉automake在何处安装列出的文件。
Automake可以识别与不同类型的文件相对应的其他元变量,例如_PROGRAMS,_LIBRARIES,_LTLIBRARIES等。
当前元
有_PROGRAMS
, _LIBRARIES
, _LTLIBRARIES
, _LISP
, _PYTHON
, _JAVA
, _SCRIPTS
, _DATA
, _HEADERS
, _MANS
, _TEXINFOS
。
将没有前缀的元
定义为变量(例如 PROGRAMS
)是错误的!
1.4.2.3. 目录
某些变量用于确定应该把创建了的对象安装在哪里。这些变量中在元
前面的部分指示了应将哪个标准目录作为安装目录。标准目录名在GNU标准中给出(参考GUN编码标准中的目录变量)。automake通过前缀pkg
扩展了这些标准目录变量,这些扩展的与标准的相同,但附加了$(PACKAGE)
。例如:
GNU编码标准中的目录变量,如:prefix
、exec_prefix
、bindir
、libdir
、includedir
、datarootdir
、datadir
等。
在构造变量名称时,通用的dir
后缀被保留了。因此,使用bin_PROGRAMS
而不是bindir_PROGRAMS
。在使用automake扩展目录时,同样适用于此规则。例如,以下代码片段会将./CMakeLists.txt安装到$(datadir)/cmake
文件夹中。
cmakedatadir = $(datadir)/cmake
nobase_dist_cmakedata_DATA = ./CMakeLists.txt
在autotools中,编译和安装的规则是在一起的:安装目录_编译类型=编译目标
1.4.2.4. 前缀
某些元
还可由一个或者多个前缀和变量串联起来形成。某些前缀如下:
-
EXTRA_
对于每个
元
,都可以插入一个EXTRA_
前缀。该前缀用于储存根据configure的运行结果,可能创建、也可能不创建的对象列表。引入该变量是因为Automake必须静态地知道需要创建的对象的完整列表以创建在所有情况下都能够工作的Makefile.in
。
例如:EXTRA_LTLIBRARIES = lib1.la lib2.la
,这两个库不会被明确的构建,如果其在任何地方都不会作为Makefile依赖项出现,就不会被构建。一般该前缀用在条件编译的情形下比较常见。 -
check_
该前缀表示仅仅在运行
make check
命令的时候才创建这些对象。 -
inst_
/noinst_
用于控制
make install
时的安装行为。inst_
表示应构建相关对象,且进行安装。noinst_
表示应构建相关对象,但不安装。这通常用于构建程序包其余部分所需的对象,例如静态库或帮助程序脚本。 -
dist_
/nodist_
用于控制
make dist
时的发布行为。
任何元
或_SOURCES
变量都可以使用dist_作为前缀,以将列出的文件添加到发行版中。类似地,nodist_可用于从发行版中省略文件。
nobase_
默认情况下,在子目录中指定的可安装文件在安装前将删除其目录名称。例如,在此示例中,头文件将安装为$(cmakedatadir)/CMakeLists.txt。
dist_cmakedata_DATA += clist/CMakeLists.txt
但是,可以使用nobase_
前缀来规避此路径剥离。在此示例中,头文件将安装为$(cmakedatadir)/clist/CMakeLists.txt。
nobase_dist_cmakedata_DATA += clist/CMakeLists.txt
当与其他前缀混合出现时,应首先指定该前缀
1.4.2.5. 衍生变量
有时Makefile变量名是从用户提供的某些文本中派生而来的。例如,_PROGRAMS
中列出的程序名称将被重写为_SOURCES
变量的名称。Automake把这些文本规范化,以使它可以不必服从Makefile的变量名规则。进行变量引用时,名称中的所有字符(字母,数字,@
和下划线除外)都将变为下划线。
例如,如果程序名为sniff-glue
,则派生变量名称将为sniff_glue_SOURCES
,而不是sniff-glue_SOURCES
。同样的,名称为libmumble++.a
的库的源文件应在libmumble___a_SOURCES
变量中列出。
1.4.2.6. 用户保留变量
GNU编码标准保留了一些Makefile变量,以供“用户”(构建软件包的人)使用,这些变量有些可能会被Autoconf预设。例如:
Automake为每个用户标志变量引入了一个特定于automake的影子变量(没有为CC之类的变量引入影子变量,因为它们没有意义)。影子变量的名称是在用户变量名前加上AM_
。例如,CFLAGS
的影子变量为AM_CFLAGS
。软件包维护者(即Makefile.am和configure.ac文件的作者)可以根据需要调整这些影子变量。
1.4.2.7. 目标变量
与每个程序相关联的是变量集合,可用于修改该程序的构建方式。每个库都有类似的此类变量列表。程序或库的规范名称用作命名这些变量的基础。以程序或库名为maude
举例,常见的变量如下:
1.4.2.8. 其他
SUBDIRS
EXTRA_DIST
BUILT_SOURCES
1.4.3. Makefile.am常用变量说明
当一些头文件不需要在外部被引用时,也应该列在_SOURCES
中,而不是_HEADERS
。例如,库的头文件一般列出在_HEADERS
,程序的头文件一般列出在_SOURCES
中。另外有一些参与目标构建但既不属于目标对象,又不需要被外部引用的头文件,则可以使用noinst_HEADERS
,比较典型的如configure生成的config.h文件。
_LDADD
和_LIBADD
不适合传递程序特定的链接器标志(-l,-L,-dlopen和-dlpreopen除外)。
1.5. 一些常见问题
1.5.1. 标识变量的顺序问题
以CPPFLAGS为例,automake中有三个有关该标识变量,CPPFLAGS
、AM_CPPFLAGS
、maude_CPPFLAGS
,用于传递给C/C++预处理器,CPPFLAGS是用户变量,AM_CPPFLAGS是Automake变量,而mumble_CPPFLAGS是特定于目标对象的变量,也即每个目标变量。
编译时,automake始终使用这些变量中的两个,如果maude_CPPFLAGS
定义了,则使用该变量,否则,使用AM_CPPFLAGS,第二个变量始终是CPPFLAGS。该规则也同样适用于其他类似标记。 例如:
bin_PROGRAMS = foo bar
foo_SOURCES = xyz.c
bar_SOURCES = main.c
foo_CPPFLAGS = -DFOO
AM_CPPFLAGS = -DBAZ
xyz.o将使用$(foo_CPPFLAGS)$(CPPFLAGS)
进行编译(因为xyz.o是foo目标的一部分),而main.o将使用$(AM_CPPFLAGS)$(CPPFLAGS)
进行编译(因为bar目标变量未定义)。
推荐使用额外自定义的变量,然后使用目标对象的标记变量追加。例如:
AM_CFLAGS = $(WARNINGCFLAGS)
bin_PROGRAMS = prog1 prog2
prog1_SOURCES = ...
prog2_SOURCES = ...
prog2_CFLAGS = $(LIBFOOCFLAGS) $(AM_CFLAGS)
prog2_LDFLAGS = $(LIBFOOLDFLAGS)
1.5.2. 如何引用预定义的变量
例如想将bindir
定义到程序中使用,直接使用以下方式是行不通的:
AC_DEFINE_UNQUOTED([INSTALL_BINDIR], [$bindir], [Define to the read-only architecture-independent data directory.])
最终得到的结果是:
#define DINSTALL_BINDIR "${prefix}/bin"
因为该行为是GNU编码标准强制规定的,要达到目的,不能使用AC_DEFINE
,而是使用Makefile通过编译标识传递,或者定义到专门的头文件中。
- 方式一:使用Makefile通过编译标识传递
AM_CPPFLAGS = -DINSTALL_BINDIR='"$(bindir)"'
- 方式二:创建一个专用头文件
DISTCLEANFILES = mydefines.h
mydefines.h: Makefile
echo '#define INSTALL_BINDIR "$(bindir)"' >$@
根据配置编译不同模块
- 使用AC_DEFINE或AC_DEFINE_UNQUOTED定义C语言使用的宏
- 使用AM_CONDITIONAL或AC_SUBST定义Makefile使用的宏
配置特殊宏
- 新建一个单独的目录,用于存放自定义宏,一般定义为m4
- 为每个宏定义一个文件,以.m4结尾
- 使用AC_DEFUN定义具体的宏
- 运行aclocal -Im4生成aclocal.m4
- 在根目录下的Makefile.am中添加ACLOCAL_AMFLAGS = -I m4
1.6. clist示例工程
1.7. 参考资料
autoconf
automake
libtool
autoconf宏定义
Autotools 工具
绝世秘籍之GNU构建系统与Autotool概念分析
automake,autoconf使用详解
Autoconf中文手册