作为 UNIX/LINUX 背景下的开发人员或者运维人员,当然对
configure -> make -> make install
系列操作非常熟悉,但是可能对其实现方式不是那么熟悉,实际上,这叫GNU构建系统
,利用脚本和 make 程序在特定平台上构建软件。此次我们以开发者的视角来分析构建细节。
环境说明:
- CentOS release 6.9 (Final)
- autoconf 2.69 (包含
autoscan
autoconf
autoheader
) - automake 1.11.1 (包含
aclocal
automake
) - make 3.81
configure / make / make install
开发人员或者运维人员经常使用 configure->make->make install 三部曲进行软件安装,然后好多人并不知道这个过程真正干了什么。
configure
脚本是由软件开发者维护并发布给用户使用的shell脚本
。这个脚本的作用就是检测系统环境和进行基本的配置,最终目的生成Makefile
和config.h
make
通过读取Makefile
文件,开始构建软件- 而
make install
则负责将 软件或者可执行文件 安装至指定位置
详细请查看如下每部分详情….
项目结构
示例项目源码: autotoolsdemo
主要文件的内容如下:
|
|
|
|
|
|
|
|
流程
让我们开始
autoscan
|
|
将生成 configure.scan 和 autoscan.log,然后重命名 configure.scan 为 configure.ac
。autoscan 会扫描源码,并生成一些通用的宏调用、输入的声明以及输出的声明。尽管autoscan十分方便,但是没人能够在构建之前,就把代码完全写好,因此 autoscan 通常用于初始化 configure.ac
每个 configure.scan 文件都是以 AC_INIT开头,AC_OUTPUT 结束,布局如下
其中以 AC_ 开头的类似函数调用一样的代码,实际是一些被称为“宏”的调用。这里的宏与C中的宏概念类似,会被替换展开。m4是一个经典的宏工具,autoconf 正是构建在m4之上,可以理解为 autoconf 预先实现了大量的,用于检测系统可移植性的宏,这些宏在展开后就是大量的shell脚本。所以编写 configure.ac 需要对这些宏熟练掌握,并且合理调用。有时,甚至可以自己实现自己的宏。
aclocal
|
|
configure.in 里面包含了一系列的宏命令,运行aclocal的目的是把工程需要的宏命令展开。aclocal.m4 就是configure.in中用到的宏定义。本步会生成aclocal.m4文件和autom4te.cache文件夹
autoconf
|
|
这个命令将 configure.ac 文件中的宏展开,生成 configure 脚本。这个过程可能要用到aclocal.m4中定义的宏
autoheader
|
|
生成配置头文件的模板config.h.in文件
编写Makefile.am
automake 工具会根据 configure.in 中的参量把 Makefile.am 转换成 Makefile.in 文件。最终通过 Makefile.in 生成 Makefile 文件,所以 Makefile.am 这个文件非常重要,分别在每个目录下建立 Makefile.am
配置文件
./Makefile.am
./include/Makefile.am
./src/Makefile.am
Makefile.am是一种比Makefile更高层次的规则。只需指定要生成什么目标,它由什么源文件生成,要安装到什么目录等构成。
AUTOMAKE_OPTIONS
软件等级,automake提供了3种软件等级:foreign、gnu、gnits,默认等级是gnu。此处使用的foreign表示只是检测必要的文件SUBDIRS
先扫描子目录,多个目录用空格隔开INCLUDES
指明include目录noinst_LIBRARIES
生成静态库(.a)或者动态库(.so)的名称。库文件一般以lib.a或者lib.so来命名。而且静态库使用中,需要对configure.ac中加入AC_PROG_RANLIB
。静态库配置分为两个:noinst_LIBRARIES
:当运行make install的时候,库文件不会被安装到linux默认的/usr/local/lib目录下。lib_LIBRARIES
:当运行make intsall的时候,则会被安装到/usr/local/lib目录下。之前的例子:noinst_LIBRARIES=libthread.a
libthread_a_SOURCES
c 的源文件,多个文件用空格分开libthread_a_LDADD
加载所需的库文件libthread_a_LDFLAGS
编译的时候的连接标识bin_PROGRAMS
声明一个可执行文件目标autotoolsdemo_SOURCES
指定这个目标所依赖的源代码文件autotoolsdemo_LDADD
声明了可执行文件在连接时,需要依赖的Libtool库文件LIBS
因为我们项目中用到了pthread
,这个是动态连接,在编译的时候会自动加上-l pthread
automake
生成Makefiel.in和所需要的脚本,其中add-missing选项会让automake自动添加一些必须的脚本文件
./configure
configure 为 shell 脚本文件
当 ./configure 运行的时候,将看到很多系统检查操作,不过检查的多少一般取决于软件的需求,即由 开发者决定。
一般来说,configue 主要检查当前目标平台的 程序、库、头文件、函数 等的兼容性。这些检查结果将用于 config.h 和 Makefile 文件的生成,从而影响最后的编译
用户也可以通过 configure 配置参数来定制软件需要包含或不需要包含的组件、安装路径 等行为,这些参数分为 5组,可以通过执行 ./configure –help 查看,软件提供配置参数大致为:
- 安装路径相关配置。最常见的是 –prefix。
- 程序名配置。例如 –program-suffix 可用于为生成的程序添加后缀。
- 跨平台编译。不太常用。
- 动态库静态库选项。用于控制是否生成某种类型的库文件。
- 程序组件选项。用于配置程序是否将某种功能编译到程序中,一般形如 –with-xxx。这可能是最常用的配置,而且由软件开发者来定义。
configure在执行过程中,除了生成Makefile外,还会生成的文件包括但不限于:
- config.log 日志文件
- config.cache 缓存,以提高下一次configure的速度,需通过-C来指定才会生成
- config.status 实际调用编译工具构建软件的shell脚本
configure 经常会中途出错,这一般是由于当前平台不具有构建该软件所必需的依赖(库、函数、头文件、程序…)。此时,不要慌张,仔细查看输出,解决这些依赖
make
|
|
make install
|
|
默认安装至 /usr/local/bin/
如上所述即为 GUN构建系统的流程,类似使用较多的还有 cmake。但是更多的还是使用 IDE 进行构建。不过不可否认,作为 LINUX软件开发者,autotools 是不可避免的知识点。
本文作者: wettper
本文链接: http://www.web-lovers.com/c-autotools.html
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议。转载请注明出处!