SlideShare a Scribd company logo
autotools 入门
授人于鱼不如授人于渔

推荐阅读:
autobook
autoconf手册
automake手册

基本上到这儿,就该结束了。剩下的
就不保证绝对正确了。
autotools的作用:

1. 使代码可移植
代码可移植不是自动的,代码自身必须保证其在任意平台可以运行。autotools只是
告诉,这个平台什么可以用,什么不可以用。

2. 使安装分发很容易
# ./configure
# make
# make install
这个最初是gnu的规范,后来变成了开源的规范。

3. 看起来很专业的样子
专业,至少从看起来专业开始。但是切记,估计只有跑在虚拟机上的代码(例如
perl),和精通各个平台的人,才能写出真正可移植的代码。


我对可移植的理解:
作为公司内部项目,不必追求可移植,在linux平台运行,(只要能)就应该榨干
linux提供的每一份特性。
# info autoreconf
`autoreconf' runs `autoconf', `autoheader',
`aclocal', `automake',`libtoolize', and `autopoint'
(when appropriate) repeatedly to update the GNU
Build System in the specified directories and their
subdirectories (*note Subdirectories::). By default,
it only remakes those files that are older than their
sources.

autotools 通常说的是autoconf,automake,
autolib,但是还有很多辅助的工具,包括
autoheader,aclocal,autoscan。
这些工具的关系:
autoconf 根据configure.in(configure.ac)生成configure。
automake 根据 Makefile.am 生成Makefile.in。
autotools 是解决各个平台对.a,.so 的处理不一致的,我不懂这个,今天就不说
了。
这些都是开发者要做的。

使用者运行 ./configure 时发生的事情:
configure 检测平台特性,生成config.h,config.h 定义了很多宏,这些宏标识了平
台特性,例如:#define HAVE_MEMSET 1;说明该平台提供了memset函数;根据
Makefile.in,生成相应平台的Makefile,不同的平台,Makefile规则不同。

上面所的平台特性,其实不准确,准确的说法是,检查特性。configure不会检查这个
系统是Linux还是FreeBSD,它只检查某个函数是否得到支持。

注意:autoconf 并不依赖automake,NB的开发者可以手动写Makefile.in,例如apache
就没有Makefile.am;configure 只是一个普通的脚本,NB的开发者可以手动写
configure(只要它能完成上述功能),例如nginx的作者。


作为不NB的开发者,我们要完成configure.in文件和Makefile.am文件的编写。下面
主要讲解着两个文件。
目录结构如下:
0> ls
aclocal.m4 config.h.in configure.in jobqueue.cpp Makefile.am mysqlqueue.cpp
config     configure jobclient.pl lib            Makefile.in mysqlqueue.hpp

0> ls ./lib
conffile.cpp conffile.hpp gc.hpp Makefile.am Makefile.in pidfile.hpp

主程序文件在顶层目录,子目录lib下存放库文件。

可以看到configure.in 文件, Makefile.am Makefile.in文件,lib/Makefile.am,lib/Makefile.in
文件。

使用autoscan可以生成一个configure.in的样板文件,下面讲解confiugre.in的常用指
令。令人欣慰的是多数指令autoscan会帮我们生成。

使用>作为注释,这是方便讲解用的。

# perl -pi -e 's/^>.*$//' configure.in

这个命令去除所有以>开头的行
configure.in 由宏和shell脚本组成,宏由M4展开,shell脚本原封不动,拷贝到
configure。

四个主要的环境变量:
 CXXFLAGS C++ compiler flags
 LDFLAGS  linker flags, e.g. -L<lib dir> if you have libraries in a
          nonstandard directory <lib dir>
 CPPFLAGS C/C++ preprocessor flags, e.g. -I<include dir> if you have
          headers in a nonstandard directory <include dir>
 CFLAGS   C compiler flags

在使用configure时,要区分这四个变量,如果是c++,就不要用CFLAGS。例如:
./configure CPPFLAGS="-I/usr/local/mysql5/include" CXXFLAGS=“-g -O3"
LDFLAGS="-lmysqlclient"

一些shell变量,用在Makefile.am中
$top_srcdir 源文件顶层目录
$srcdir 当前源文件目录
#                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

> AC_PREREQ (version),要求autoconf的版本
AC_PREREQ(2.59)

> AC_INIT (package, version, [bug-report], [tarname], [url])
AC_INIT(jobqueue, 1.0, zhiyong1@staff.sina.com.cn)

> AC_CONFIG_AUX_DIR (dir),指定辅助文件的目录
> ls config
> config.guess config.sub depcomp install-sh missing
> 这些文件是autoconf生成的,要随源码发布
AC_CONFIG_AUX_DIR(config)

> AC_CONFIG_HEADERS (header)
> 生成的配置头文件的名称
AC_CONFIG_HEADER([config.h])

> AC_CONFIG_SRCDIR (unique-file-in-source-dir)
> ./configure --srcdir=DIR 指定源码目录,configure 查找 unique-file-in-source-dir,
确定指定了正确的源码目录
AC_CONFIG_SRCDIR([jobqueue.cpp])
> AC_ARG_ENABLE (feature, help-string, [action-if-given], [action-if-not-given])
> ./configure --with_debug,自定义configure的参数
> 这里自定义了一个with_debug参数,如果configure带这个参数,设置shell变量
> with_debug的值为yes,否则为no
> 根据with_debug的值,设置不同的编译参数

> AS_HELP_STRING (left-hand-side, right-hand-side)
> ./configure --help
> --with_debug       enable debug

AC_ARG_ENABLE(with_debug, AS_HELP_STRING([--with_debug],[enable
debug]), with_debug=yes, with_debug=no)
CXXFLAGS="$CXXFLAGS -g -Wall -Wno-comment -Wformat -Wimplicit -
Wparentheses -Wswitch -Wunused -Wshadow"
if test $with_debug = "yes"; then
    CXXFLAGS="$CXXFLAGS -O0 -DDEBUG -D_DEBUG_"
else
    CXXFLAGS="$CXXFLAGS -O2 -DNDEBUG"
fi

> AC_PREFIX_DEFAULT (prefix)
> 指定默认安装目录,如果不指定是/usr/local
AC_PREFIX_DEFAULT([/usr/local/jobqueue])
> AM_MAINTAINER_MODE([default-mode])
> automake使用,根据一定的规则,重新生成 configure Makefile.in
AM_MAINTAINER_MODE([enable])

> AM_INIT_AUTOMAKE([OPTIONS])
> automake的运行参数,指定foreign,automake仅检查必须的文件
> 例如,NEWS文件是gnu的标准,指定foreign将不检查NEWS文件是否存在
AM_INIT_AUTOMAKE([foreign])

# Checks for programs.
> 检查c++编译器
AC_PROG_CXX
> 检查c编译器
AC_PROG_CC
> 检查链接器
AC_PROG_LD
> 检查ranlib程序
AC_PROG_RANLIB
> 检查install 程序
AC_PROG_INSTALL
> AC_CHECK_LIB (library, function, [action-if-found], [action-if-not-found],
>                    [other-libraries])
> 指定libcurl中的一个函数(curl_easy_init), 检查是否有libcurl库
> 如果没有指定action-if-found,且找到了libcurl 库,则默认添加-lcurl到LIBS
> 如果没有指定action-if-not-found,且没有找到libcurl 库,则默认不退出configure
> 如果需要改变默认行为,用下面检查mysqlclient的方法
# Checks for libraries.
# FIXME: Replace `main' with a function in `-lcurl':
AC_CHECK_LIB([curl], [curl_easy_init])

> 检查mysqlclient库,如果存在,增加一个头文件查找位置(-I),
> 增加一个头文件查找位置的原因,下页介绍。
> 如果没找到AC_MSG_ERROR 报错,退出configure
# FIXME: Replace `main' with a function in `-lmysqlclient':
AC_CHECK_LIB([mysqlclient], [mysql_init],
       [LIBS="-lmysqlclient $LIBS"
        CPPFLAGS="-I/usr/local/mysql/include $CPPFLAGS"
        LDFLAGS="-L/usr/local/mysql/lib $LDFLAGS"],
       AC_MSG_ERROR([can't find mysqlclient]))

AC_CHECK_LIB的原理下面介绍
AC_CHECK_LIB 的检查原理是,生成一小段代码,在这段代码中调用指定的函数,如
果这段代码通过编译,则这个库通过检查。
char mysql_init ();
int
main ()
{
mysql_init ();
  ;
  return 0;
}

这段代码就是AC_CHECK_LIB([mysqlclient],[mysql_init]) 生成的代码。可以看出
mysql_init的声明和mysql.h中的不一样,并且也没有包含mysql.h头文件。只要
gcc tmp.c -lmysqlclient 能编译通过就行了,它也不保证一定能找到mysql.h头文件。这
也是我们在检查mysqlclient时,增加一个头文件包含目录的原因。

事实上,不可奢求太多,configure怎么可能知道mysql_init的返回值呢?

聪明如你,一定会问,c++怎么办,我要包括的库就是一个类?没有函数?如何写
AC_CHECK_LIB呢?而且,此时是一定要看到头文件的。

AC_CHECK_LIB 不支持c++类的检查。但是autoconf支持自定义检查代码。事实上,
AC_CHECK_LIB 的原理,就是我根据下面的代码,猜出来的。
> AC_LANG (language)
> 指定检查代码的语言
AC_LANG(C++)

> AC_COMPILE_IFELSE (input, [action-if-true], [action-if-false])
> 编译input中的代码
> AC_LANG_PROGRAM (prologue, body)
> 生成代码段,prologue中的内容放在main外,body放到main里
AC_COMPILE_IFELSE(
  AC_LANG_PROGRAM([[#include <threadpool.hpp>]],
             [ThreadPool pool(1, 1)]),
  [LIBS="-lthreadpool $LIBS"],
  AC_MSG_ERROR([can't find threadpool])
)

注意这段代码仅检查了能否“编译”,没检查“链接”,我检查编译通过,添加了相
应的-l。检查链接用AC_LINK_IFELSE,并且要保证LIBS里面有相应的-l。

代码段如下:
#include <threadpool.hpp>
int
main ()
{
ThreadPool pool(1, 1)
  ;
  return 0;
}
> 检查dirent.h
AC_HEADER_DIRENT

> 检查标准c头文件
AC_HEADER_STDC

> AC_CHECK_HEADERS (header-file..., [action-if-found], [action-if-not-found],
[includes])
> 检查相应的头文件是否存在。
AC_CHECK_HEADERS([fcntl.h stdint.h string.h sys/file.h sys/time.h unistd.h])

# Checks for typedefs, structures, and compiler characteristics.
> 检查一些typedef,数据结构
AC_HEADER_STDBOOL
AC_C_CONST
AC_C_INLINE
AC_TYPE_OFF_T
AC_TYPE_SIZE_T
AC_HEADER_TIME
AC_STRUCT_TM
> 检查库函数
# Checks for library functions.
AC_FUNC_FSEEKO
AC_FUNC_SETVBUF_REVERSED
AC_TYPE_SIGNAL
AC_FUNC_STRFTIME
AC_CHECK_FUNCS([dup2 ftruncate gettimeofday localtime_r memset strerror
strstr])

> 如果库函数dup2有定义,#define HAVE_DUP2 1

> 到这些目录找Makefile文件
AC_CONFIG_FILES([Makefile lib/Makefile])

> configure.in 结束
AC_OUTPUT
下面讲解Makefile.am

> make的顺序,例如先编译基础库,再编译应用代码。
SUBDIRS   = lib .

> include 的目录
INCLUDES      = -I$(top_srcdir)/lib

> bin_PROGRAMS,编译目标
bin_PROGRAMS = jobqueue

> 目标jobqueue依赖的源文件
jobqueue_SOURCES = mysqlqueue.cpp mysqlqueue.hpp jobqueue.cpp
> 目标jobqueue需要链接的库
jobqueue_LDADD = lib/libstdx.a

> 不需要编译,只需要分发的脚本
dist_bin_SCRIPTS = jobclient.pl
> 额外需要分发的其他东西
EXTRA_DIST          = jobqueue.conf
> 安装时需要执行的命令
install-data-local:
   mkdir -p $(DESTDIR)$(prefix)/conf
   mkdir -p $(DESTDIR)$(prefix)/logs
   $(INSTALL_DATA) $(top_srcdir)/jobqueue.conf $(DESTDIR)$(prefix)/conf
下面讲解src/Makefile.am

> 不需要安装的库
noinst_LIBRARIES = libstdx.a

> 这个库依赖的文件
libstdx_a_SOURCES = conffile.cpp conffile.hpp gc.hpp

> 编译成.a的.o
libstdx_a_ADDLIB = @LIBOBJS@
分发简介

打包源文件
# make dist

检查打包是否完整
# make distcheck

清理 
# make distclean

生成
我们很容易弄糊涂,修改了configure.in的那些地方需要调用什么,修改了
Makefile.am需要调用什么,为此推荐命令 autoreconf -ivf

调试
configure执行错误,主要检查是宏还是shell错误,宏错误多和宏的函数有关,shell
错误和通常的shell错误没啥区别
make错误,主要看看Makefile.am的依赖有没有写对

结束
以上介绍,可能有不准确的地方,如有疑问,最好翻查相应的文档

Q&A

More Related Content

PPTX
Nevermore Unit Testing
PDF
Alfresco study presentation 38th customize How-To WebDAV
DOCX
Nginx 0.9.x 安装手册
PPTX
Bypassing anti virus using powershell
PDF
はじめてのSymfony2
PDF
Zend\Expressive - höher, schneller, weiter
PDF
Security and dev ops for high velocity organizations
PDF
What happens in laravel 4 bootstraping
Nevermore Unit Testing
Alfresco study presentation 38th customize How-To WebDAV
Nginx 0.9.x 安装手册
Bypassing anti virus using powershell
はじめてのSymfony2
Zend\Expressive - höher, schneller, weiter
Security and dev ops for high velocity organizations
What happens in laravel 4 bootstraping

What's hot (20)

PDF
Silex and Twig (PHP Dorset talk)
PDF
Continuous Quality Assurance
PDF
CodePolitan Webinar: The Rise of PHP
PPTX
Controlling multiple VMs with the power of Python
PDF
Monitoring OSGi Applications with the Web Console - Carsten Ziegeler
PDF
LibreSSL
PDF
Take a Jailbreak -Stunning Guards for iOS Jailbreak- by Kaoru Otsuka
PDF
실시간 서비스 플랫폼 개발 사례
PDF
Silex: From nothing to an API
PDF
AWSをテラフォーミングする会(Terraformハンズオン)
PPTX
Ansible intro
PDF
Build Web Apps using Node.js
PDF
Composer, putting dependencies on the score
PPT
Topic
PPTX
2019 Chef InSpec Jumpstart Part 2 of 2
PDF
kubernetes practice
DOCX
Como instalar aeroo en open erp 6
PDF
Hyperledger composer
PPTX
InSpec Workshop at Velocity London 2018
PPTX
Basics of Ansible - Sahil Davawala
Silex and Twig (PHP Dorset talk)
Continuous Quality Assurance
CodePolitan Webinar: The Rise of PHP
Controlling multiple VMs with the power of Python
Monitoring OSGi Applications with the Web Console - Carsten Ziegeler
LibreSSL
Take a Jailbreak -Stunning Guards for iOS Jailbreak- by Kaoru Otsuka
실시간 서비스 플랫폼 개발 사례
Silex: From nothing to an API
AWSをテラフォーミングする会(Terraformハンズオン)
Ansible intro
Build Web Apps using Node.js
Composer, putting dependencies on the score
Topic
2019 Chef InSpec Jumpstart Part 2 of 2
kubernetes practice
Como instalar aeroo en open erp 6
Hyperledger composer
InSpec Workshop at Velocity London 2018
Basics of Ansible - Sahil Davawala
Ad

Viewers also liked (20)

PPT
Something About The Web
PDF
Marketing Return On Investment White Paper
PDF
Social media: a revolution in local government communications?
PPT
Flashstoryboardfor Val
PPS
生命銀行
PPS
In A Concert
PPT
Assignment Fireworks
PPT
Deforestation
PPTX
在Sae上开发高性能微博应用
PPT
What charities really think of online giving, and how to make the most of it
PPT
Publizitate Eraginkortasunaren Baliospena 4
PPT
SAP Slides (28.10.09) Web
PPT
Weather Presentation
PPT
Importance Of Being Driven
PPT
Advent - Otvorenost
PPT
El Pollo Loco
PDF
St Ann's Hospice and Social Media - IoF North West Annual Conference 2009
PPT
为什么你需要了解应用云
PDF
Amy&Per Erik
PPS
Roysville
Something About The Web
Marketing Return On Investment White Paper
Social media: a revolution in local government communications?
Flashstoryboardfor Val
生命銀行
In A Concert
Assignment Fireworks
Deforestation
在Sae上开发高性能微博应用
What charities really think of online giving, and how to make the most of it
Publizitate Eraginkortasunaren Baliospena 4
SAP Slides (28.10.09) Web
Weather Presentation
Importance Of Being Driven
Advent - Otvorenost
El Pollo Loco
St Ann's Hospice and Social Media - IoF North West Annual Conference 2009
为什么你需要了解应用云
Amy&Per Erik
Roysville
Ad

Similar to Autotools (20)

DOC
X64服务器 lnmp服务器部署标准 new
PPT
Autoconf&Automake
PDF
Dependencies Managers in C/C++. Using stdcpp 2014
PPTX
InSpec For DevOpsDays Amsterdam 2017
DOCX
Nginx 0.8.x 安装手册
PPTX
Capistrano与jenkins(hudson)在java web项目中的实践
PPTX
DevOpsDays InSpec Workshop
PPTX
BuildStuff.LT 2018 InSpec Workshop
PDF
Ansible - Hands on Training
PPTX
One Click Provisioning With Enterprise Manager 12c
PDF
Writing Rust Command Line Applications
PDF
Autotools
PDF
DevOps(4) : Ansible(2) - (MOSG)
PDF
Ansible Tutorial.pdf
PDF
Continous Delivering a PHP application
PPTX
Infrastructure as code - Python Saati #36
PDF
Web backdoors attacks, evasion, detection
ODP
Autotools
PDF
Building an HPC Cluster in 10 Minutes
PPTX
Feature and platform testing with CMake
X64服务器 lnmp服务器部署标准 new
Autoconf&Automake
Dependencies Managers in C/C++. Using stdcpp 2014
InSpec For DevOpsDays Amsterdam 2017
Nginx 0.8.x 安装手册
Capistrano与jenkins(hudson)在java web项目中的实践
DevOpsDays InSpec Workshop
BuildStuff.LT 2018 InSpec Workshop
Ansible - Hands on Training
One Click Provisioning With Enterprise Manager 12c
Writing Rust Command Line Applications
Autotools
DevOps(4) : Ansible(2) - (MOSG)
Ansible Tutorial.pdf
Continous Delivering a PHP application
Infrastructure as code - Python Saati #36
Web backdoors attacks, evasion, detection
Autotools
Building an HPC Cluster in 10 Minutes
Feature and platform testing with CMake

More from easychen (11)

PDF
IDF2013大会分享——《使用新浪移动云开发全平台应用》
PDF
互联网商品设计
PDF
TeamToy-创新团队的效率工具
PDF
我是产品经理我需不需要学技术
PDF
10min mobile-app
PDF
新浪云平台的经验和教训
PPT
Qt编程介绍
PPT
Android应用开发简介
PDF
如何利用社会化网络制造流行潮
PDF
写给技术人员的产品指南
PPT
为什么你需要了解应用云
IDF2013大会分享——《使用新浪移动云开发全平台应用》
互联网商品设计
TeamToy-创新团队的效率工具
我是产品经理我需不需要学技术
10min mobile-app
新浪云平台的经验和教训
Qt编程介绍
Android应用开发简介
如何利用社会化网络制造流行潮
写给技术人员的产品指南
为什么你需要了解应用云

Recently uploaded (20)

PDF
Machine learning based COVID-19 study performance prediction
PDF
Empathic Computing: Creating Shared Understanding
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
PPTX
MYSQL Presentation for SQL database connectivity
PPTX
PA Analog/Digital System: The Backbone of Modern Surveillance and Communication
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PDF
Agricultural_Statistics_at_a_Glance_2022_0.pdf
PPTX
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
PDF
Approach and Philosophy of On baking technology
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PDF
Network Security Unit 5.pdf for BCA BBA.
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
DOCX
The AUB Centre for AI in Media Proposal.docx
PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
PDF
NewMind AI Monthly Chronicles - July 2025
PDF
Unlocking AI with Model Context Protocol (MCP)
PDF
KodekX | Application Modernization Development
PDF
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
PDF
Modernizing your data center with Dell and AMD
PDF
Encapsulation theory and applications.pdf
Machine learning based COVID-19 study performance prediction
Empathic Computing: Creating Shared Understanding
20250228 LYD VKU AI Blended-Learning.pptx
MYSQL Presentation for SQL database connectivity
PA Analog/Digital System: The Backbone of Modern Surveillance and Communication
Per capita expenditure prediction using model stacking based on satellite ima...
Agricultural_Statistics_at_a_Glance_2022_0.pdf
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
Approach and Philosophy of On baking technology
Advanced methodologies resolving dimensionality complications for autism neur...
Network Security Unit 5.pdf for BCA BBA.
Diabetes mellitus diagnosis method based random forest with bat algorithm
The AUB Centre for AI in Media Proposal.docx
The Rise and Fall of 3GPP – Time for a Sabbatical?
NewMind AI Monthly Chronicles - July 2025
Unlocking AI with Model Context Protocol (MCP)
KodekX | Application Modernization Development
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
Modernizing your data center with Dell and AMD
Encapsulation theory and applications.pdf

Autotools

  • 3. autotools的作用: 1. 使代码可移植 代码可移植不是自动的,代码自身必须保证其在任意平台可以运行。autotools只是 告诉,这个平台什么可以用,什么不可以用。 2. 使安装分发很容易 # ./configure # make # make install 这个最初是gnu的规范,后来变成了开源的规范。 3. 看起来很专业的样子 专业,至少从看起来专业开始。但是切记,估计只有跑在虚拟机上的代码(例如 perl),和精通各个平台的人,才能写出真正可移植的代码。 我对可移植的理解: 作为公司内部项目,不必追求可移植,在linux平台运行,(只要能)就应该榨干 linux提供的每一份特性。
  • 4. # info autoreconf `autoreconf' runs `autoconf', `autoheader', `aclocal', `automake',`libtoolize', and `autopoint' (when appropriate) repeatedly to update the GNU Build System in the specified directories and their subdirectories (*note Subdirectories::). By default, it only remakes those files that are older than their sources. autotools 通常说的是autoconf,automake, autolib,但是还有很多辅助的工具,包括 autoheader,aclocal,autoscan。
  • 5. 这些工具的关系: autoconf 根据configure.in(configure.ac)生成configure。 automake 根据 Makefile.am 生成Makefile.in。 autotools 是解决各个平台对.a,.so 的处理不一致的,我不懂这个,今天就不说 了。 这些都是开发者要做的。 使用者运行 ./configure 时发生的事情: configure 检测平台特性,生成config.h,config.h 定义了很多宏,这些宏标识了平 台特性,例如:#define HAVE_MEMSET 1;说明该平台提供了memset函数;根据 Makefile.in,生成相应平台的Makefile,不同的平台,Makefile规则不同。 上面所的平台特性,其实不准确,准确的说法是,检查特性。configure不会检查这个 系统是Linux还是FreeBSD,它只检查某个函数是否得到支持。 注意:autoconf 并不依赖automake,NB的开发者可以手动写Makefile.in,例如apache 就没有Makefile.am;configure 只是一个普通的脚本,NB的开发者可以手动写 configure(只要它能完成上述功能),例如nginx的作者。 作为不NB的开发者,我们要完成configure.in文件和Makefile.am文件的编写。下面 主要讲解着两个文件。
  • 6. 目录结构如下: 0> ls aclocal.m4 config.h.in configure.in jobqueue.cpp Makefile.am mysqlqueue.cpp config configure jobclient.pl lib Makefile.in mysqlqueue.hpp 0> ls ./lib conffile.cpp conffile.hpp gc.hpp Makefile.am Makefile.in pidfile.hpp 主程序文件在顶层目录,子目录lib下存放库文件。 可以看到configure.in 文件, Makefile.am Makefile.in文件,lib/Makefile.am,lib/Makefile.in 文件。 使用autoscan可以生成一个configure.in的样板文件,下面讲解confiugre.in的常用指 令。令人欣慰的是多数指令autoscan会帮我们生成。 使用>作为注释,这是方便讲解用的。 # perl -pi -e 's/^>.*$//' configure.in 这个命令去除所有以>开头的行
  • 7. configure.in 由宏和shell脚本组成,宏由M4展开,shell脚本原封不动,拷贝到 configure。 四个主要的环境变量: CXXFLAGS C++ compiler flags LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a nonstandard directory <lib dir> CPPFLAGS C/C++ preprocessor flags, e.g. -I<include dir> if you have headers in a nonstandard directory <include dir> CFLAGS C compiler flags 在使用configure时,要区分这四个变量,如果是c++,就不要用CFLAGS。例如: ./configure CPPFLAGS="-I/usr/local/mysql5/include" CXXFLAGS=“-g -O3" LDFLAGS="-lmysqlclient" 一些shell变量,用在Makefile.am中 $top_srcdir 源文件顶层目录 $srcdir 当前源文件目录
  • 8. # -*- Autoconf -*- # Process this file with autoconf to produce a configure script. > AC_PREREQ (version),要求autoconf的版本 AC_PREREQ(2.59) > AC_INIT (package, version, [bug-report], [tarname], [url]) AC_INIT(jobqueue, 1.0, zhiyong1@staff.sina.com.cn) > AC_CONFIG_AUX_DIR (dir),指定辅助文件的目录 > ls config > config.guess config.sub depcomp install-sh missing > 这些文件是autoconf生成的,要随源码发布 AC_CONFIG_AUX_DIR(config) > AC_CONFIG_HEADERS (header) > 生成的配置头文件的名称 AC_CONFIG_HEADER([config.h]) > AC_CONFIG_SRCDIR (unique-file-in-source-dir) > ./configure --srcdir=DIR 指定源码目录,configure 查找 unique-file-in-source-dir, 确定指定了正确的源码目录 AC_CONFIG_SRCDIR([jobqueue.cpp])
  • 9. > AC_ARG_ENABLE (feature, help-string, [action-if-given], [action-if-not-given]) > ./configure --with_debug,自定义configure的参数 > 这里自定义了一个with_debug参数,如果configure带这个参数,设置shell变量 > with_debug的值为yes,否则为no > 根据with_debug的值,设置不同的编译参数 > AS_HELP_STRING (left-hand-side, right-hand-side) > ./configure --help > --with_debug enable debug AC_ARG_ENABLE(with_debug, AS_HELP_STRING([--with_debug],[enable debug]), with_debug=yes, with_debug=no) CXXFLAGS="$CXXFLAGS -g -Wall -Wno-comment -Wformat -Wimplicit - Wparentheses -Wswitch -Wunused -Wshadow" if test $with_debug = "yes"; then CXXFLAGS="$CXXFLAGS -O0 -DDEBUG -D_DEBUG_" else CXXFLAGS="$CXXFLAGS -O2 -DNDEBUG" fi > AC_PREFIX_DEFAULT (prefix) > 指定默认安装目录,如果不指定是/usr/local AC_PREFIX_DEFAULT([/usr/local/jobqueue])
  • 10. > AM_MAINTAINER_MODE([default-mode]) > automake使用,根据一定的规则,重新生成 configure Makefile.in AM_MAINTAINER_MODE([enable]) > AM_INIT_AUTOMAKE([OPTIONS]) > automake的运行参数,指定foreign,automake仅检查必须的文件 > 例如,NEWS文件是gnu的标准,指定foreign将不检查NEWS文件是否存在 AM_INIT_AUTOMAKE([foreign]) # Checks for programs. > 检查c++编译器 AC_PROG_CXX > 检查c编译器 AC_PROG_CC > 检查链接器 AC_PROG_LD > 检查ranlib程序 AC_PROG_RANLIB > 检查install 程序 AC_PROG_INSTALL
  • 11. > AC_CHECK_LIB (library, function, [action-if-found], [action-if-not-found], > [other-libraries]) > 指定libcurl中的一个函数(curl_easy_init), 检查是否有libcurl库 > 如果没有指定action-if-found,且找到了libcurl 库,则默认添加-lcurl到LIBS > 如果没有指定action-if-not-found,且没有找到libcurl 库,则默认不退出configure > 如果需要改变默认行为,用下面检查mysqlclient的方法 # Checks for libraries. # FIXME: Replace `main' with a function in `-lcurl': AC_CHECK_LIB([curl], [curl_easy_init]) > 检查mysqlclient库,如果存在,增加一个头文件查找位置(-I), > 增加一个头文件查找位置的原因,下页介绍。 > 如果没找到AC_MSG_ERROR 报错,退出configure # FIXME: Replace `main' with a function in `-lmysqlclient': AC_CHECK_LIB([mysqlclient], [mysql_init], [LIBS="-lmysqlclient $LIBS" CPPFLAGS="-I/usr/local/mysql/include $CPPFLAGS" LDFLAGS="-L/usr/local/mysql/lib $LDFLAGS"], AC_MSG_ERROR([can't find mysqlclient])) AC_CHECK_LIB的原理下面介绍
  • 12. AC_CHECK_LIB 的检查原理是,生成一小段代码,在这段代码中调用指定的函数,如 果这段代码通过编译,则这个库通过检查。 char mysql_init (); int main () { mysql_init (); ; return 0; } 这段代码就是AC_CHECK_LIB([mysqlclient],[mysql_init]) 生成的代码。可以看出 mysql_init的声明和mysql.h中的不一样,并且也没有包含mysql.h头文件。只要 gcc tmp.c -lmysqlclient 能编译通过就行了,它也不保证一定能找到mysql.h头文件。这 也是我们在检查mysqlclient时,增加一个头文件包含目录的原因。 事实上,不可奢求太多,configure怎么可能知道mysql_init的返回值呢? 聪明如你,一定会问,c++怎么办,我要包括的库就是一个类?没有函数?如何写 AC_CHECK_LIB呢?而且,此时是一定要看到头文件的。 AC_CHECK_LIB 不支持c++类的检查。但是autoconf支持自定义检查代码。事实上, AC_CHECK_LIB 的原理,就是我根据下面的代码,猜出来的。
  • 13. > AC_LANG (language) > 指定检查代码的语言 AC_LANG(C++) > AC_COMPILE_IFELSE (input, [action-if-true], [action-if-false]) > 编译input中的代码 > AC_LANG_PROGRAM (prologue, body) > 生成代码段,prologue中的内容放在main外,body放到main里 AC_COMPILE_IFELSE( AC_LANG_PROGRAM([[#include <threadpool.hpp>]], [ThreadPool pool(1, 1)]), [LIBS="-lthreadpool $LIBS"], AC_MSG_ERROR([can't find threadpool]) ) 注意这段代码仅检查了能否“编译”,没检查“链接”,我检查编译通过,添加了相 应的-l。检查链接用AC_LINK_IFELSE,并且要保证LIBS里面有相应的-l。 代码段如下: #include <threadpool.hpp> int main () { ThreadPool pool(1, 1) ; return 0; }
  • 14. > 检查dirent.h AC_HEADER_DIRENT > 检查标准c头文件 AC_HEADER_STDC > AC_CHECK_HEADERS (header-file..., [action-if-found], [action-if-not-found], [includes]) > 检查相应的头文件是否存在。 AC_CHECK_HEADERS([fcntl.h stdint.h string.h sys/file.h sys/time.h unistd.h]) # Checks for typedefs, structures, and compiler characteristics. > 检查一些typedef,数据结构 AC_HEADER_STDBOOL AC_C_CONST AC_C_INLINE AC_TYPE_OFF_T AC_TYPE_SIZE_T AC_HEADER_TIME AC_STRUCT_TM
  • 15. > 检查库函数 # Checks for library functions. AC_FUNC_FSEEKO AC_FUNC_SETVBUF_REVERSED AC_TYPE_SIGNAL AC_FUNC_STRFTIME AC_CHECK_FUNCS([dup2 ftruncate gettimeofday localtime_r memset strerror strstr]) > 如果库函数dup2有定义,#define HAVE_DUP2 1 > 到这些目录找Makefile文件 AC_CONFIG_FILES([Makefile lib/Makefile]) > configure.in 结束 AC_OUTPUT
  • 16. 下面讲解Makefile.am > make的顺序,例如先编译基础库,再编译应用代码。 SUBDIRS = lib . > include 的目录 INCLUDES = -I$(top_srcdir)/lib > bin_PROGRAMS,编译目标 bin_PROGRAMS = jobqueue > 目标jobqueue依赖的源文件 jobqueue_SOURCES = mysqlqueue.cpp mysqlqueue.hpp jobqueue.cpp > 目标jobqueue需要链接的库 jobqueue_LDADD = lib/libstdx.a > 不需要编译,只需要分发的脚本 dist_bin_SCRIPTS = jobclient.pl > 额外需要分发的其他东西 EXTRA_DIST = jobqueue.conf > 安装时需要执行的命令 install-data-local: mkdir -p $(DESTDIR)$(prefix)/conf mkdir -p $(DESTDIR)$(prefix)/logs $(INSTALL_DATA) $(top_srcdir)/jobqueue.conf $(DESTDIR)$(prefix)/conf
  • 17. 下面讲解src/Makefile.am > 不需要安装的库 noinst_LIBRARIES = libstdx.a > 这个库依赖的文件 libstdx_a_SOURCES = conffile.cpp conffile.hpp gc.hpp > 编译成.a的.o libstdx_a_ADDLIB = @LIBOBJS@
  • 18. 分发简介 打包源文件 # make dist 检查打包是否完整 # make distcheck 清理  # make distclean 生成 我们很容易弄糊涂,修改了configure.in的那些地方需要调用什么,修改了 Makefile.am需要调用什么,为此推荐命令 autoreconf -ivf 调试 configure执行错误,主要检查是宏还是shell错误,宏错误多和宏的函数有关,shell 错误和通常的shell错误没啥区别 make错误,主要看看Makefile.am的依赖有没有写对 结束 以上介绍,可能有不准确的地方,如有疑问,最好翻查相应的文档 Q&A