automake连载---关于两个文件configure.in和Makefile.am的编写
2015-09-09 09:21
351 查看
automake主要通过编辑Makefile.am来控制它的行为,下面就常用的三个Makefile.am配置做出说明。
l autoscan
l aclocal
l autoheader
l autoconf
l automake
另外,还需要有两类输入文件:configure.in和Makefile.am。其中,configure.in是用来生成configure脚本的,configure脚本的作用主要有两个:检测系统的环境,生成Makefile。而Makefile.am则是生成Makefile的参数,它们之间是一一对应的。一般来说,在一个工程中每个目录下都会有一个Makefile来管理当前目录下的文件。所以,基本上每个目录中都需要编写一个Makefile.am,来描述当前目录下生成的Makefile的行为。
有了生成工具和输入文件,下面来看一下生成Makefile的流程,如下图所示:
需要说明的是autoscan工具的使用,autoscan检测当前目录下的所有文件,生成一个configure.scan,这个文件可以作为configure.in文件的雏形,在它的基础上稍做修改就可以作为configure.in文件来使用。所以,autoscan工具只需要在工程创建时运行一次即可。
下面就来具体介绍两个输入文件的编写规则:
表1.2.1 Makefile.am中的规则
其中,生成动态库的同时还会自动生成一个静态库,所以在一般情况下都不直接使用静态库规则。
Makefile.am中还有一些可以直接使用的全局变量,表示所有目标所共享的一些属性,见下表:
表1.2.2 Makefile.am中的变量
有了以上的规则和变量,我们可以完成最基本的Makefile.am编写,但在某些情况下,我们需要定义一些变量来控制工程中某些目标的生成:比如库的版本号是不断变化的,需要定义一个变量来指代。Makefile.am可以使用宏替换来实现这种功能,可以通过以下方式来引用一个宏:
@宏名@
这个宏的的定义是在configure.in中的,在1.3.节中会介绍它的定义方法。
现在Makefile.am中所需要了解的规则和语法已经介绍完了,下面介绍一下如何使用这些规则来具体生成一个库和可执行程序。
lib_LTLIBRARIES = hello.la
hello_la_SOURCES = hello1.cpp hello2.cpp
hello_la_LIBADD = -lworld
hello_la_LDFLAGS = -version-info 1.0.10
可以看到,在LIBADD规则中链接库文件的方法与使用g++编译时的相同。但LDFLAGS规则中的属性就没有见过了。实际上,这个参数是传给libtool生成库时使用的,除了-version-info这个参数之外,LDFLAGS编译库时还会经常使用下面两个参数:
l -avoid-version 生成不带版本号的库
l -all-static 生成为静态库
bin_PROGRAMS = main
main_ SOURCES = main.cpp
main_ LDADD = -lhello
main_LDFLAGS = -I./include
AC_INIT(package_name, package_version, owner_email)
AC_CONFIG_FILES([makefile1_path
makefile2_path])
AC_INIT()选项中指明了工程的名字,当前工程的版本号,工程所有者的邮箱。
AC_CONFIG_FILES()中指明了所有要生成的Makefile的相对路径,由于每个Makefile都需要一个Makefile.am作参数,所以该选项中Makefile的数量和路径应与当前工程中Makefile.am的状态一致。
在经过上面的修改之后,一个configure.in文件就基本可以使用了,但通常情况下,我们需要对它进行更多的配置。
hello=nihao
但使用这个变量的方法就有些不同了,比如我们要将hello这个变量赋给hi这个变量,我们可以这样写:
hi=”$hello”
如果这个变量需要被外部引用的话(如在1.2.1节中提到的Makefile.am引用configure.in中定义的变量),需要一个额外的选项来完成,如我们要将hello定义为外部变量,可以写成:
AC_SUBST(hello)
而Makefile.am中也就可以通过对它的引用来完成对某些可变因子的替换,在Makefile.am中的引用方法见1.2.1节。
--enable-xxx 和 --disable-xxx
--with-xxx 和 --with-out-xxx
可以分别通过以下2个宏来定义这两个参数:
AC_ENABLE (feature, action-if-given, [action-if-not-given])
AC_ARG_WITH (package, help-string, [action-if-given], [action-if-not-given])
这两种格式基本上可以互换,下面就以AC_ARG_WITH()为例,说明如何给configure加上一个自定义参数。
假设我们要增加一个选项表示是否需要编译一个名为agent的模块,可以这样写:
BUILD_AGENT=no
AC_ARG_WITH([agent],
[AS_HELP_STRING([--with-agent],
[build agent(default is no)])],
[BUILD_AGENT=yes],
[BUILD_AGENT=no])
if test "x$BUILD_AGENT" = "xyes";then#判断是否加上了该参数
#做出相应动作
fi
这样,./configure就新添了两个选项--with-agent和--with-out-agent,通过这两个选项可以控制变量BUILD_AGENT的值,然后做出相应的动作。
1.1. autotools的工作原理
autotools最终是为了生成Makefile,为此,需要使用到autotools系列工具的如下几个命令:l autoscan
l aclocal
l autoheader
l autoconf
l automake
另外,还需要有两类输入文件:configure.in和Makefile.am。其中,configure.in是用来生成configure脚本的,configure脚本的作用主要有两个:检测系统的环境,生成Makefile。而Makefile.am则是生成Makefile的参数,它们之间是一一对应的。一般来说,在一个工程中每个目录下都会有一个Makefile来管理当前目录下的文件。所以,基本上每个目录中都需要编写一个Makefile.am,来描述当前目录下生成的Makefile的行为。
有了生成工具和输入文件,下面来看一下生成Makefile的流程,如下图所示:
需要说明的是autoscan工具的使用,autoscan检测当前目录下的所有文件,生成一个configure.scan,这个文件可以作为configure.in文件的雏形,在它的基础上稍做修改就可以作为configure.in文件来使用。所以,autoscan工具只需要在工程创建时运行一次即可。
下面就来具体介绍两个输入文件的编写规则:
1.2. 编写Makefile.am
1.2.1. Makefile.am规则
Makefile.am写起来相对简单,有共有5类规则,如下表表1.2.1 Makefile.am中的规则
文件类型 | 书写格式 |
可执行文件 | bin_PROGRAMS = foo foo_SOURCES = xxx.c xxxx.c foo_LDADD = foo_LDFLAGS = foo_DEPENDENCIES = |
静态库 | lib_LIBRARIES = foo.a foo_a_SOURCES = xxx.c xxxx.c foo_a_LDADD = foo_a_LIBADD = foo_a_LDFLAGS = |
动态库 | lib_LTLIBRARIES = foo.la foo_la_SOURCES = xxx.c xxxx.c foo_la_LDADD = foo_la_LIBADD = foo_la_LDFLAGS = |
头文件 | include_HEADERS = foo.h noinst_HEADERS = foo2.h |
数据文件 | data_DATA = data1 data2 |
Makefile.am中还有一些可以直接使用的全局变量,表示所有目标所共享的一些属性,见下表:
表1.2.2 Makefile.am中的变量
变量 | 含义 |
INCLUDES | 编译时所需头文件 |
LDADD | 链接时所需链接的库文件 |
LDFLAGS | 链接时的选项 |
AM_CXXFLAGS | 编译.cpp文件时的选项 |
AM_CFLAGS | 编译.c文件时的选项 |
EXTRA_DIST | 除源代码和一些默认的文件以外,其它需要打如发布包.tar.gz中的文件 |
SUBDIRS | 在处理本目录之前要递归处理的子目录 |
top_srcdir | 工程源码的最顶层目录 |
top_builddir | 工程目标文件的最顶层目录 |
@宏名@
这个宏的的定义是在configure.in中的,在1.3.节中会介绍它的定义方法。
现在Makefile.am中所需要了解的规则和语法已经介绍完了,下面介绍一下如何使用这些规则来具体生成一个库和可执行程序。
1.2.2. 库的生成
要生成一个库,需要在Makefile.am中加入一套动态库规则(见表1.2.1),如现在要用hello1.cpp和hello2.cpp两个源文件生成动态库libhello.so,库的版本为1.0.10,库需要额外连接一个叫做libworld.so的库,我们可以这样写:lib_LTLIBRARIES = hello.la
hello_la_SOURCES = hello1.cpp hello2.cpp
hello_la_LIBADD = -lworld
hello_la_LDFLAGS = -version-info 1.0.10
可以看到,在LIBADD规则中链接库文件的方法与使用g++编译时的相同。但LDFLAGS规则中的属性就没有见过了。实际上,这个参数是传给libtool生成库时使用的,除了-version-info这个参数之外,LDFLAGS编译库时还会经常使用下面两个参数:
l -avoid-version 生成不带版本号的库
l -all-static 生成为静态库
1.2.3. 可执行文件的生成
要生成一个可执行文件,需要加入一套可执行文件的规则(见表1.2.1),与生成动态库的规则很类似。下面我们要使用源文件main.cpp生成可执行文件main,该可执行文件需要链接上面生成的库libhello.so,我们可以这样写:bin_PROGRAMS = main
main_ SOURCES = main.cpp
main_ LDADD = -lhello
main_LDFLAGS = -I./include
1.3. 编写configure.in文件
与Makefile.am相比,configure.in文件写起来更复杂,因为configure.in文件中可以使用的资源要远多与Makefile.am。但通常情况下,我们都可以借助autoscan工具帮助我们生成一个configure.in的模版,在此基础上再完善就可以了。所以,实际上我们只需要在configure.in中修改以下两个参数就可以了:AC_INIT(package_name, package_version, owner_email)
AC_CONFIG_FILES([makefile1_path
makefile2_path])
AC_INIT()选项中指明了工程的名字,当前工程的版本号,工程所有者的邮箱。
AC_CONFIG_FILES()中指明了所有要生成的Makefile的相对路径,由于每个Makefile都需要一个Makefile.am作参数,所以该选项中Makefile的数量和路径应与当前工程中Makefile.am的状态一致。
在经过上面的修改之后,一个configure.in文件就基本可以使用了,但通常情况下,我们需要对它进行更多的配置。
1.3.1. 在configure.in中定义外部变量
在configure.in中定义变量与写shell脚本时定义变量的语法相同,如我们要定义一个值为nihao的变量hello,我们可以这样写:hello=nihao
但使用这个变量的方法就有些不同了,比如我们要将hello这个变量赋给hi这个变量,我们可以这样写:
hi=”$hello”
如果这个变量需要被外部引用的话(如在1.2.1节中提到的Makefile.am引用configure.in中定义的变量),需要一个额外的选项来完成,如我们要将hello定义为外部变量,可以写成:
AC_SUBST(hello)
而Makefile.am中也就可以通过对它的引用来完成对某些可变因子的替换,在Makefile.am中的引用方法见1.2.1节。
1.3.2. 给configure配置自定义参数
对于一个已经生成好的configure,执行./configure --help命令可以看到该脚本所支持的所有参数,其中大部分是其自带的。同样,我们可以通过对configure.in的配置来给它添加新的参数。可以配置的参数种类有很多种,常用的有以下2种格式:--enable-xxx 和 --disable-xxx
--with-xxx 和 --with-out-xxx
可以分别通过以下2个宏来定义这两个参数:
AC_ENABLE (feature, action-if-given, [action-if-not-given])
AC_ARG_WITH (package, help-string, [action-if-given], [action-if-not-given])
这两种格式基本上可以互换,下面就以AC_ARG_WITH()为例,说明如何给configure加上一个自定义参数。
假设我们要增加一个选项表示是否需要编译一个名为agent的模块,可以这样写:
BUILD_AGENT=no
AC_ARG_WITH([agent],
[AS_HELP_STRING([--with-agent],
[build agent(default is no)])],
[BUILD_AGENT=yes],
[BUILD_AGENT=no])
if test "x$BUILD_AGENT" = "xyes";then#判断是否加上了该参数
#做出相应动作
fi
这样,./configure就新添了两个选项--with-agent和--with-out-agent,通过这两个选项可以控制变量BUILD_AGENT的值,然后做出相应的动作。
相关文章推荐
- 计算机网络- 可靠数据传输协议-设计和实施的协议,如停止的
- 一个基于jquery的智能提示控件intellSeach.js
- KiB、MiB与KB、MB的区别
- HDU 3605 Escape 建图状态压缩
- 接口和抽象类的区别与联系
- centos6.3下安装phpredisadmin,以及配置文件
- 百度地图SDK引用问题 Symbol(s) not found for architecture armv64
- Cocoa编码规范
- 通达OA 小飞鱼老师OA工作流设计课程教学网络公开课之HTML基础(二)
- 通达OA 小飞鱼老师OA工作流设计课程教学网络公开课之HTML基础(二)
- $ionicActionSheet在Android设备上显示错乱
- STP基本配置
- java.util.ConcurrentModificationException
- Nodejs课堂笔记—第一课:修改Webstorm的默认主题
- linux使脚本在后台运行
- [Unity]C#.数据类型总结
- 【Java EE 学习 35 下】【struts2】【struts2文件上传】【struts2自定义拦截器】【struts2手动验证】
- Android Handler Runnable Message Thread 简单用法
- vc int64 数据操作
- ECshop 数据库表结构