<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>绿色记忆 &#187; GNU</title>
	<atom:link href="https://blog.gmem.cc/tag/gnu/feed" rel="self" type="application/rss+xml" />
	<link>https://blog.gmem.cc</link>
	<description></description>
	<lastBuildDate>Tue, 21 Apr 2026 10:40:56 +0000</lastBuildDate>
	<language>en-US</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.9.14</generator>
	<item>
		<title>AutoTools学习笔记</title>
		<link>https://blog.gmem.cc/autotools-study-note</link>
		<comments>https://blog.gmem.cc/autotools-study-note#comments</comments>
		<pubDate>Fri, 30 Dec 2011 14:03:52 +0000</pubDate>
		<dc:creator><![CDATA[Alex]]></dc:creator>
				<category><![CDATA[C]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[GNU]]></category>

		<guid isPermaLink="false">http://blog.gmem.cc/?p=4073</guid>
		<description><![CDATA[<p>GNU构建系统 可移植性代码的需求 开发一个C程序时，为了在不同环境下运行，可能需要考虑这些问题： 某些函数在某些环境下不存在，例如strtod() 同样功能的函数，名字不同，例如strchr() 与 index() 函数名称冲突，例如int setpgrp(void)、setpgrp(int, int) 函数在不同环境下行为不同，例如malloc(0) 函数可能定义在不同的头文件中，例如string.h 、 strings.h 、memory.h 为了解决这些问题，可以： 创建替换宏（substitution macros） 创建替换函数（substitution functions） 手工处理这类问题非常繁琐，1991年人们开始编写Shell脚本，来猜测GNU环境的设置，最终形成了configure这个工具： 探测系统中所需的函数、库、工具是否存在，根据结果生成config.h这个头文件，里面包含很多#define <a class="read-more" href="https://blog.gmem.cc/autotools-study-note">[...]</a></p>
<p>The post <a rel="nofollow" href="https://blog.gmem.cc/autotools-study-note">AutoTools学习笔记</a> appeared first on <a rel="nofollow" href="https://blog.gmem.cc">绿色记忆</a>.</p>
]]></description>
				<content:encoded><![CDATA[<div class="wri_content_clear_both"><div class="blog_h1"><span class="graybg">GNU构建系统</span></div>
<div class="blog_h2"><span class="graybg">可移植性代码的需求</span></div>
<p>开发一个C程序时，为了在不同环境下运行，可能需要考虑这些问题：</p>
<ol>
<li>某些函数在某些环境下不存在，例如strtod()</li>
<li>同样功能的函数，名字不同，例如strchr() 与 index()</li>
<li>函数名称冲突，例如int setpgrp(void)、setpgrp(int, int)</li>
<li>函数在不同环境下行为不同，例如malloc(0)</li>
<li>函数可能定义在不同的头文件中，例如string.h 、 strings.h 、memory.h</li>
</ol>
<p>为了解决这些问题，可以：</p>
<ol>
<li>创建替换宏（substitution macros）</li>
<li>创建替换函数（substitution functions）</li>
</ol>
<p>手工处理这类问题非常繁琐，1991年人们开始编写Shell脚本，来猜测GNU环境的设置，最终形成了configure这个工具：</p>
<ol>
<li>探测系统中所需的函数、库、工具是否存在，根据结果生成config.h这个头文件，里面包含很多#define</li>
<li>生成构建软件包的Makefile文件</li>
</ol>
<div class="blog_h2"><span class="graybg">标准文件系统层次结构（Standard File System Hierarchy）</span></div>
<p>现在configure文件一般由AutoConf生成，默认情况下遵循如下的目录约定，这些目录决定如何安装程序的可执行文件、库、文档等内容：</p>
<table style="width: 100%;" border="1" cellspacing="0" cellpadding="5">
<thead>
<tr>
<td style="width: 150px; text-align: center;"> 变量</td>
<td style="text-align: center;">默认值 </td>
</tr>
</thead>
<tbody>
<tr>
<td>prefix</td>
<td>/usr/local</td>
</tr>
<tr>
<td>exec-prefix</td>
<td>$(prefix)</td>
</tr>
<tr>
<td>bindir</td>
<td>$(exec-prefix)/bin</td>
</tr>
<tr>
<td>libdir</td>
<td>$(exec-prefix)/lib</td>
</tr>
<tr>
<td>includedir</td>
<td>$(prefix)/include</td>
</tr>
<tr>
<td>datarootdir</td>
<td>$(prefix)/share</td>
</tr>
<tr>
<td>datadir</td>
<td>$(datarootdir)</td>
</tr>
<tr>
<td>mandir</td>
<td>$(datarootdir)/man</td>
</tr>
<tr>
<td>infodir</td>
<td>$(datarootdir)/info</td>
</tr>
</tbody>
</table>
<p>注：上述变量均可以作为configure的命令行参数使用，例如<pre class="crayon-plain-tag">./configure --bindir=$HOME/bin</pre> </p>
<div class="blog_h2"><span class="graybg">configure的用法示例</span></div>
<p>执行<pre class="crayon-plain-tag">./configure --help</pre> 可以看到configure的完整帮助，下面给出一些示例：</p>
<pre class="crayon-plain-tag">./configure

#指定目录前缀
./configure --prefix ~/usr
#指定程序前后缀
./configure --program-prefix=hello --program-suffix=exe

#configure自动检测很多设置，可以强制使用配置变量：
#      CC  C compiler command
#  CFLAGS  C compiler  flags
#     CXX  C++ compiler command
#CXXFLAGS  C++ compiler flags
# LDFLAGS  linker flags
#CPPFLAGS  C/C++ preprocessor flags
#使用./configure --help可获取完整列表
./configure --prefix ~/usr CC=gcc-3 CPPFLAGS=-I$HOME/usr/include LDFLAGS=-L$HOME/usr/lib

#配置交叉编译
#--build=BUILD，软件包在其上被编译的系统，一般就是当前系统，由config.guess猜测即可
#--host=HOST，编译好的库、可执行文件在其上运行的系统。只有在交叉编译的时候，才和--builid即本机不同
#--target=TARGET，只有在建立交叉编译环境时才用得到，正常编译/交叉编译都用不到。用于编译一套编译器，该编译器编译出的程序在target机器上运行
./configure --build i686-pc-linux-gnu --host i586-mingw32msvc
#checking for i586-mingw32msvc-strip... i586-mingw32msvc-strip
#checking for i586-mingw32msvc-gcc... i586-mingw32msvc-gcc
#checking for C compiler default output file name... a.exe
#checking whether the C compiler works... yes
#checking whether we are cross compiling... yes
#checking for suffix of executables... .exe
#checking for suffix of object files... o
#checking whether we are using the GNU C compiler... yes
#checking whether i586-mingw32msvc-gcc accepts -g... yes
#checking for i586-mingw32msvc-gcc option to accept ANSI C...

#依赖追踪仅仅在源代码改变以后需要，在install时可以安全禁用
.configure --disable-dependency-tracking</pre>
<div class="blog_h1"><span class="graybg">GNU Autotools</span></div>
<div class="blog_h2"><span class="graybg">Hello World</span></div>
<p>假设在src目录下有如下一简单C程序：</p>
<pre class="crayon-plain-tag">#include 
#include 
int main(void)
{
    puts("HelloWorld!"); 
    return 0;
}</pre>
<p>相关文件将按如下依赖关系生成：<img class="aligncenter  wp-image-4134" src="https://blog.gmem.cc/wp-content/uploads/2011/12/configure.helloworld-1024x671.png" alt="configure.helloworld" width="687" height="450" /></p>
<p>输入文件列表：</p>
<pre class="crayon-plain-tag">#初始化Autoconf，指定软件包的名称、版本号、缺陷报告地址
AC_INIT([amhello], [1.0], [bug-report@gmem.cc])
#初始化Automake，启用Automake警告，并将其报告为错误
AM_INIT_AUTOMAKE([foreign -Wall -Werror])
#检查C编译器
AC_PROG_CC
#声明config.h为输出头文件
AC_CONFIG_HEADERS([config.h])
#声明Makefile、src/Makefile为输出文件
AC_CONFIG_FILES([Makefile src/Makefile])
#输出所有声明的文件
AC_OUTPUT</pre><br />
<pre class="crayon-plain-tag">#在src目录下递归的构建，可以声明多个SUBDIR，顺序非常重要
SUBDIRS = src
#对于根目录，无任何其他声明</pre><br />
<pre class="crayon-plain-tag">#PROGRAMS表示在构建某个程序
#bin表示程序将安装在bin目录(默认/usr/local/bin)
#仅有一个名为hello的程序需要构建
bin_PROGRAMS = hello
#为了构建程序hello，需要编译main.c
hello_SOURCES = main.c</pre>
<p>生成configure、Makefile已经构建、打包的命令示意： </p>
<pre class="crayon-plain-tag">cd ~/amhello
autoreconf --install
#输出内容：
# configure.ac:2: installing './install-sh'
# configure.ac:2: installing './missing'
# src/Makefile.am: installing './depcomp'
#自动生成以下文件：
#Makefile.in、config.h.in、Makefile.in、configure*是配置模板文件
#aclocal.m4是configure.ac中使用的第三方宏定义
#depcomp* install-sh* missing*是构建过程中的辅助工具
#Autotools缓存文件：autom4te.cache/ : output.0 requests traces.1 output.1 traces.0

./configure
#checking...
#生成Makefile
#configure: creating ./config.status
#config.status: creating Makefile
#config.status: creating src/Makefile
#config.status: creating config.h
#config.status: executing depfiles commands

make
make distcheck
#========================================
#amhello archives ready for distribution:
#amhello-1.0.tar.gz
#========================================
tar ztf amhello-1.0.tar.gz</pre>
<div class="blog_h2"><span class="graybg">Autotools核心工具包</span></div>
<div class="blog_h3"><span class="graybg">GNU Autoconf包</span></div>
<table style="width: 100%;" border="1" cellspacing="0" cellpadding="5">
<thead>
<tr>
<td style="width: 150px; text-align: center;">工具 </td>
<td style="text-align: center;">说明 </td>
</tr>
</thead>
<tbody>
<tr>
<td>autoconf</td>
<td>
<p>一个宏处理器（底层是GNU M4，但是带有很多预定义宏），从configure.ac（一个带有宏指令的Shell脚本）生成configure（一个完整的Shell脚本）</p>
</td>
</tr>
<tr>
<td>autoheader</td>
<td>从configure.ac生成config.h.in</td>
</tr>
<tr>
<td>autoreconf</td>
<td>按正确顺序运行所有工具</td>
</tr>
<tr>
<td>autoscan</td>
<td>扫描源代码以发现常见的可移植性问题、以及缺失的configure.ac中的宏定义</td>
</tr>
<tr>
<td>autoupdate</td>
<td>更新configure.ac中废弃的宏定义</td>
</tr>
<tr>
<td>ifnames</td>
<td>从#if/#ifdef/...指令中收集标识符</td>
</tr>
<tr>
<td>autom4te</td>
<td>Autoconf的核心，驱动M4、实现上面工具需要的特性</td>
</tr>
</tbody>
</table>
<p>Autoconf提供多种宏来进行常见的配置检查，仅包含宏定义、没有任何Shell语句的congure.ac也是常见的。</p>
<p><span style="background-color: #c0c0c0;"><strong>Autoconf与M4</strong></span><br /> Autoconf底层的宏处理器是M4，下面是其一个简单的例子：</p>
<pre class="crayon-plain-tag">#test.m4
m4_define(NAME1, Harry)    #宏参数会被处理。宏会被展开
m4_define(NAME2, Sally)    #宏参数参数可以用引号保护，例如 'Sally Wang'
m4_define(MET, $1 met $2)  #宏名称和参数之间不能有空格。引号前面的空格被忽略，引号中间、后面的空格被作为参数的内容
MET(NAME1, NAME2)

#测试
m4 -P test.m4
#输出
#
#
#
#Harry met Sally</pre>
<p>由于引号'的特殊用途，因此，<span style="background-color: #c0c0c0;">在Autoconf中，使用[]来代替''，Shell中不能使用[进行条件判断，而需要使用if test语句</span>。</p>
<pre class="crayon-plain-tag">#Autoconf中的条件测试：
if test "$x" = "$y"; then ...

#使用AC DEFUN可以定义宏
AC_DEFUN([NAME1], [Harry, Jr.])
AC_DEFUN([NAME2], [Sally])
AC_DEFUN([MET], [$1 met $2])
MET([NAME1], [NAME2])</pre>
<p><span style="background-color: #c0c0c0;"><strong>configure.ac的组成与预定义宏</strong></span></p>
<table style="width: 100%;" border="1" cellspacing="0" cellpadding="5">
<thead>
<tr>
<td style="width: 200px; text-align: center;"> 组成</td>
<td style="text-align: center;">说明以及重要的宏</td>
</tr>
</thead>
<tbody>
<tr>
<td>准备（Prelude）</td>
<td>
<pre class="crayon-plain-tag">#强制Autoconf的初始化
AC_INIT(PACKAGE, VERSION, BUG-REPORT-ADDRESS)
#启用Automake，并进行初始化，检查依赖的工具是否存在
AM_INIT_AUTOMAKE([OPTIONS...])
#要求Autoconf的最低版本
AC_PREREQ(VERSION)
#例如install-sh、depcomp之类构建辅助脚本的存放目录
AC_CONFIG_AUX_DIR(DIRECTORY)</pre>
</td>
</tr>
<tr>
<td>检查程序</td>
<td>
<pre class="crayon-plain-tag">#编译器检查，如果需要的话处理交叉编译器的搜索
AC_PROG_CC, AC_PROG_CXX, AC_PROG_F77
#寻找适合的实现，并设置$SED $YACC $LEX
AC_PROG_SED, AC_PROG_YACC, AC_PROG_LE
#设置VAR为第一个寻找到的PROGS，如果找不到，则设置为VAL-IF-NOT-FOUND
AC_CHECK_PROGS(VAR, PROGS, [VAL-IF-NOT-FOUND])
#举例：
AC_CHECK_PROGS([TAR], [tar gtar], [:])
if test "$TAR" = :; then
    AC_MSG_ERROR([This package needs tar.])
fi</pre>
</td>
</tr>
<tr>
<td>检查库</td>
<td>
<pre class="crayon-plain-tag">#检查__LIBRARY是否存在，是否包含FUNCT，并根据检查结果分别执行ACT-IF-FOUND、ACT-IF-NOT
#如果ACT-IF-FOUND没有设置，则默认行为是：
#1、LIBS="-l__LIBRARY $LIBS" （Automake使用$LIBS进行链接）
#2、定义#define HAVE_LIB__LIBRARY
AC_CHECK_LIB(__LIBRARY, FUNCT, [ACT-IF-FOUND], [ACT-IF-NOT])</pre>
</td>
</tr>
<tr>
<td>检查头文件</td>
<td>
<pre class="crayon-plain-tag">#检查每一个头文件，并定义C宏：#define HAVE_HEADER_H
AC_CHECK_HEADERS(HEADERS...)

AC_CHECK_HEADERS([sys/param.h unistd.h])
AC_CHECK_HEADERS([wchar.h])

#可能添加如下的宏定义:HAVE_SYS_PARAM_H, HAVE_UNISTD_H, HAVE_WCHAR_H
#if HAVE_UNISTD_H
#include &lt;unistd.h&gt;
#endif

#检查一个头文件
AC_CHECK_HEADER(HEADER, [ACT-IF-FOUND], [ACT-IF-NOT]) </pre>
</td>
</tr>
<tr>
<td>输出文件</td>
<td>
<pre class="crayon-plain-tag">#从HEADER.h.in文件导出HEADER.h
AC_CONFIG_HEADERS(HEADERS...)
#从FILE.in文件导出FILE
#注意*.in是模板文件，其中的@XYZ@为占位符
#自动使用AC_SUBST定义的变量替换
AC_CONFIG_FILES(FILES...)</pre>
</td>
</tr>
<tr>
<td>动作</td>
<td>
<pre class="crayon-plain-tag">#打印ERROR-DESCRIPTION并退出
AC_MSG_ERROR(ERROR-DESCRIPTION, [EXIT-STATUS])
#打印警告信息
AC_MSG_WARN(ERROR-DESCRIPTION)
#输出C宏定义到config.h
AC_DEFINE(VARIABLE, VALUE, DESCRIPTION)

/* DESCRIPTION */
#define VARIABLE VALUE

#在Makefile中定义VARIABLE为VALUE
AC_SUBST(VARIABLE, [VALUE])</pre>
</td>
</tr>
</tbody>
</table>
<div class="blog_h3"><span class="graybg">GNU Automake包</span></div>
<table style="width: 100%;" border="1" cellspacing="0" cellpadding="5">
<thead>
<tr>
<td style="width: 150px; text-align: center;"><span style="color: #333333; font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; font-size: small;"> 工具</span></td>
<td style="text-align: center;"><span style="color: #333333; font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; font-size: small;">说明 </span></td>
</tr>
</thead>
<tbody>
<tr>
<td><span style="color: #333333; font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; font-size: small;">automake</span></td>
<td><span style="color: #333333; font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; font-size: small;">从Makefile.am、configure.ac推导出Makefile.in</span></td>
</tr>
<tr>
<td><span style="color: #333333; font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; font-size: small;">aclocal</span></td>
<td><span style="color: #333333; font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; font-size: small;">扫描configure.ac中使用的第三方宏定义、收集aclocal.m4中的定义</span></td>
</tr>
</tbody>
</table>
<p>Automake辅助生成可移植的、GNU标准兼容的Makefile，它从简单的Makefile.am文件生成复杂的Makefile.in文件。</p>
<p>Makefile.am具有和Makefile类似的语法形式，但是通常只包含变量定义，Automake根据这些定义创建构建规则。<span style="background-color: #c0c0c0;">在Makefile.am中包含额外的Makefile规则是允许的</span>，Automake会将其保留，并输出到最终的Makefile。</p>
<p><span style="background-color: #c0c0c0;"><strong>在configure.ac中声明使用Automake</strong></span></p>
<p>使用宏<span style="color: #000000;">AM_INIT_AUTOMAKE([OPTIONS...])，可以在configure.ac中声明Automake，OPTIONS包括：</span></p>
<table style="width: 100%;" border="1" cellspacing="0" cellpadding="5">
<thead>
<tr>
<td style="width: 100px; text-align: center;"> 选项</td>
<td style="text-align: center;">说明 </td>
</tr>
</thead>
<tbody>
<tr>
<td>-Wall</td>
<td>开启所有警告</td>
</tr>
<tr>
<td>-Werror</td>
<td>将警告报告为错误</td>
</tr>
<tr>
<td>foreign</td>
<td>放松某些GNU标准的要求</td>
</tr>
<tr>
<td>1.11.1</td>
<td>要求最低1.11.1版本的Automake</td>
</tr>
<tr>
<td>dist-bzip2</td>
<td>在执行make dist、make distcheck时自动创建tar.bz2文件</td>
</tr>
<tr>
<td>tar-ustar</td>
<td>使用ustar格式创建tar归档文件</td>
</tr>
</tbody>
</table>
<p><span style="background-color: #c0c0c0;"><strong>使用宏AC_CONFIG_FILES(FILES...)声明输出文件</strong></span></p>
<p>Automake会为每一个存在FILE.am的FILE创建对应的FILE.in（模板）文件</p>
<pre class="crayon-plain-tag">#自动生成Makefile.am、sub/Makefile.am文件
AC_CONFIG_FILES([Makefile sub/Makefile])</pre>
<p><span style="background-color: #c0c0c0;"><strong>Makefile.am中的where_PRIMARY惯例 </strong></span></p>
<pre class="crayon-plain-tag">#使用如下形式（下划线分隔的三段字符串）声明目标
option_where_PRIMARY = targets ...

#其中option：
#dist 分发targets，默认
#nodist 不分发targets

#其中where： targets将被安装在（遵从标准文件系统层次结构）
#bin $(bindir)
#lib $(libdir)
#custom $(customdir ) 自定义目录
#noinst 不进行安装
#check 以 make check方式构建

#其中PRIMARY： targets被构建为何种组件
#PROGRAMS 可执行程序
#LIBRARIES 库
#LTLIBRARIES Libtool库
#HEADERS 头文件
#SCRIPTS 脚本
#DATA 数据</pre>
<p><span style="background-color: #c0c0c0;"><strong>按目标设置标记</strong></span></p>
<pre class="crayon-plain-tag">#假设foo是一个程序或者库
#默认值：foo_XXXFLAGS = $(AM_XXXFLAGS)
foo_CFLAGS    #额外的C编译器标记
foo_CPPFLAGS  #额外的预处理器标记（-I、-D）
foo_LDADD     #foo为程序时：额外的链接对象、-l、-L
foo_LIBADD    #foo为库时：额外的链接对象、-l、-L
foo_LDFLAGS   #额外的连接器标记

#对于软件包内部的额外链接对象，应当保留原始的文件名
#-l、-L仅用于外部库
run_me_LDADD = ../lib/libcompat.a</pre>
<p><span style="background-color: #c0c0c0;"><strong>声明源代码文件</strong></span></p>
<pre class="crayon-plain-tag">#目标foo、run-me编译为可执行程序，安装到bin目录
bin_PROGRAMS = foo run-me
#foo的源代码列表
foo_SOURCES = foo.c foo.h print.c print.h
#run-me的源代码列表（注意非alphanumeric字符-映射为_）
run_me_SOURCES = run.c run.h print.c
#注意：
#Automake自动计算从这些文件构建、链接的object列表
#头文件不是必须的，只是为了分发的需要，Automake不会分发不知道的文件
#可以为两个程序使用同样的Source
#根据.h、.c扩展名来推断是在编译、链接阶段使用某个原文件</pre>
<p><span style="background-color: #c0c0c0;"><strong>Automake举例：静态库</strong></span></p>
<pre class="crayon-plain-tag">#目标libfoo.a、libbar.a作为库安装到$(libdir)
lib_LIBRARIES = libfoo.a libbar.a #注意名称必须满足lib*.a形式
#s声明两个目录的源代码文件
libfoo_a_SOURCES = foo.c privfoo.h
libbar_a_SOURCES = bar.c privbar.h
#目标foo.h、bar.h（公共头文件）被安装到$(includedir)
include_HEADERS = foo.h bar.h</pre>
<p><span style="background-color: #c0c0c0;"><strong>Makefile.am的目录布局</strong></span></p>
<p>注意每个目录下均需要一个Makefile文件，因此也就对应了Makefile.am文件。并且这些Makefile必须在configure.ac中一一声明，例如：</p>
<pre class="crayon-plain-tag">AC_CONFIG_FILES([Makefile lib/Makefile src/Makefile src/dira/Makefile src/dirb/Makefile])</pre>
<p>make命令是在根目录运行的，Makefile.am可以声明构建子目录的顺序：</p>
<pre class="crayon-plain-tag">SUBDIRS = lib src</pre><br />
<pre class="crayon-plain-tag">SUBDIRS = dira dirb .
#注意，默认当前目录在子目录构建完成后构建
#可以移动当前目录（.）的位置，改变此默认行为</pre>
<p><span style="background-color: #c0c0c0;"><strong> Parallel Build Trees (即VPATH Builds)</strong></span></p>
<p>VPATH用于指定一组make需要搜索的目录的列表。</p>
<p>obj文件、程序、库在configure运行的$CWD下构建，但是源代码不一定需要在$CWD下——所谓构建树（build tree）、源码树（source tree）：</p>
<ol>
<li>Makefile、obj文件等处于构建树</li>
<li>Makefile.in、Makefile.am、源代码等位于源码树</li>
</ol>
<p>如果./configure在$CWD中运行，则两棵树一致，每个Makefile的config.status会定义$(srcdir)，用来指定对应的源码目录</p>
<p><span style="background-color: #c0c0c0;"><strong>辅助库（Convenience Libraries）</strong></span></p>
<p>所谓辅助库，是指仅仅在构建过程中使用的临时库：</p>
<pre class="crayon-plain-tag">noinst_LIBRARIES = libcompat.a  #noinst表示其为临时的
libcompat_a_SOURCES = xalloc.c xalloc.h</pre><br />
<pre class="crayon-plain-tag">LDADD = ../lib/libcompat.a  #使用临时库，LDADD在链接所有程序时自动添加
AM_CPPFLAGS = -I$(srcdir)/../lib #AM_CPPFLAGS包含额外的预处理标记
bin_PROGRAMS = foo run-me
foo_SOURCES = foo.c foo.h print.c print.h
run_me_SOURCES = run.c run.h print.c
#注意LDADD、AM_CPPFLAGS 也可以按目标逐一指定，以应用于一个程序
run_me_LDADD = ../lib/libcompat.a
run_me_CPPFLAGS = -I$(srcdir)/../lib</pre>
<p><span style="background-color: #c0c0c0;"><strong>检查依赖库</strong></span></p>
<pre class="crayon-plain-tag">#检查一个依赖库中的某个函数是否存在，并采取相应的动作
AC_CHECK_LIB(LIBRARY, FUNCT, [ACT-IF-FOUND], [ACT-IF-NOT])

#举例：
AC_CHECK_LIB([efence], [malloc], [EFENCELIB=-lefence]) #如果存在，则定义变量
AC_SUBST([EFENCELIB]) #在Makefile中声明变量</pre><br />
<pre class="crayon-plain-tag">run_me_LDADD = ../lib/libcompat.a $(EFENCELIB)</pre>
<p><span style="background-color: #c0c0c0;"><strong>哪些文件被分发（Distributed）</strong></span></p>
<p>&nbsp;</p>
<ol>
<li>所有使用***_SOURCES声明的源代码</li>
<li>所有使用***_HEADERS声明的头文件</li>
<li>所有使用dist_***_ SCRIPTS声明的脚本文件</li>
<li>所有使用dist_***_ DATA声明的数据文件</li>
<li>诸如ChangeLog, NEWS之类的常规文件</li>
<li>EXTRA_DIST中列出的额外目录或者文件</li>
</ol>
<p><span style="background-color: #c0c0c0;"><strong>条件构建（Conditional builds）</strong></span></p>
<pre class="crayon-plain-tag">bin_PROGRAMS = foo
#如果此变量为真，构建bar程序。但即使为假，也会分发
#WANT_BAR必须在configure.ac中声明和使用
if WANT_BAR  
  bin_PROGRAMS += bar
endif
foo_SOURCES = foo.c
bar_SOURCES = bar.c</pre><br />
<pre class="crayon-plain-tag">#条件构建的声明，如果CONDITION指定的Shell指令成功，则NAME为真
AM_CONDITIONAL(NAME, CONDITION)

#举例：
AC_CHECK_HEADER([bar.h], [use_bar=yes])
AM_CONDITIONAL([WANT_BAR], [test "$use_bar" = yes])</pre>
<p><span style="background-color: #c0c0c0;"><strong>扩展Automake规则</strong></span></p>
<ol>
<li>Makefile.am中的内容几乎是逐字的复制到Makefile.in</li>
<li>automake添加新的规则、变量到Makefile.in，以实现必须定义的变量的语义</li>
<li>某些较小的Makefile.in重写是通过条件构建来实现的</li>
<li>在Makefile.am中添加自己的规则是可以的，例如这些规则：
<ol>
<li>对维护有意义的目标的规则：例如make style-check</li>
<li>用于构建特殊目标的规则：例如为某些文件生成FAQ</li>
</ol>
</li>
<li>可以定义对Automake无意义的变量，例如在自定义规则中使用</li>
</ol>
<p><span style="background-color: #c0c0c0;"><strong>make命令失败时该怎么办</strong></span></p>
<pre class="crayon-plain-tag">#在必要时尝试下面的方法

#手工运行autoreconf
autoreconf --install

#仍然无效，可以尝试
autoreconf --install --force

#甚至
make -k maintainer-clean
autoreconf --install --force</pre>
<p>&nbsp;</p>
</div><p>The post <a rel="nofollow" href="https://blog.gmem.cc/autotools-study-note">AutoTools学习笔记</a> appeared first on <a rel="nofollow" href="https://blog.gmem.cc">绿色记忆</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.gmem.cc/autotools-study-note/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
