分类: LINUX
2009-03-13 18:37:22
创建automake项目 step by step
1. 创建好项目目录以及子目录
本文例子目录树结构:
project
|
|-- Makefile.am [项目根目录 Makefile.am]
|-- common[common子目录]
| |
| |---Makefile.am [项目子目录 Makefile.am]
| |
| |---test[test 子文件夹]
| |----Makefile.am [项目子目录测试子目录 Makefile.am]
|
|-- opt [opt子目录]
| |
| |---Makefile.am [项目子目录 Makefile.am]
| |
| |---test[test 子文件夹]
| |----Makefile.am [项目子目录测试子目录 Makefile.am]
|
|
|-- exe [exe子目录]
|
|---Makefile.am [项目子目录 Makefile.am]
|
|---test[test 子文件夹]
|----Makefile.am [项目子目录测试子目录 Makefile.am]
2. 进入项目根目录
执行流程图:
a. autoscan-->"configure.scan"
b. mv configure.scan [configure.in|configure.ac]
c. vim [configure.in|configure.ac]
d. vim Makefile.am [for each src dir]
e. aclocal -----|
d. autoconf -----|-----> "configure"
f. automake -a --------> "Makefile.in" [for each src dir]
g. ./configure --arguments ----> Makefile [for each src dir]
h. make
i. make install
f. make dist -----"xxxx.tar.gz"
2.1 编写configure.in
整个configure.in[ac]文件的编写过程按以下步骤。
2.1.0 文件模板:
#步骤一: 项目初始化设置 project init set
AC_INIT(file)
#步骤五: 项目编译期检查 project compile checks
#checks for programs
#checks for libraries
#checks for header files
#checks for typedefs
#checks for structures
#checks for compiler characteristics
#checks for library functions
#checks for system services
#步骤二: 项目选项设置 project custom options set
#步骤三: 项目选项变量导出 options varies export to makefile
#步骤四: 项目文件输出设置 project outputs file set
AC_OUTPUT([file...])
2.1.1 步骤一: 项目初始化设置
2.1.1.1 初始化设置 必填项
AC_INIT (package, version, [bug-report], [tarname])
2.1.1.2 项目文件验证, 选填项
AC_CONFIG_SRCDIR (unique-file-in-source-dir)
2.1.1.3 automake支持 必填项
AM_INIT_AUTOMAKE([OPTIONS])
AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
选一个宏进行定义
2.1.1.4 项目目录设置,选填项(强烈建议使用)
AC_PREFIX_DEFAULT (prefix)
设置项目默认安装路径,未定义情况下,目录是 /usr/local
ex:
AC_PREFIX_DEFAULT ([`pwd`])
2.1.1.5 NOTICE设置,选填项
AC_PREREQ (version)
AC_COPYRIGHT (copyright-notice)
AC_REVISION (revision-info)
2.1.2 步骤二: 项目选项设置 project custom options set
2.1.2.1 项目安装外部包选项(很少使用)
AC_ARG_WITH (package, help-string [, action-if-given [, action-if-not-given]])
2.1.2.2 项目安装自定义选项(肯定使用)
AC_ARG_ENABLE (feature, help-string [, action-if-given [, action-if-not-given]])
如果用户以选项`--enable-feature'或者`--disable-feature'调用 configure,就运行shell命令action-if-given。
如果两个选项都没有给出,就运行shell命令 action-if-not-given。
名称feature表示可选的用户级功能。
它应该仅仅由字母、数字和破折号(dashes)组成。
shell命令可以通过访问shell变量enableval来得到选项的参数,
该变量的值实际上就是把shell变量 enable_feature的值中所有的`-'字符替换成`_'而得到的。
如果你愿意,可以使用变量enable_feature。
ex:
AC_ARG_ENABLE([ssl],
[AC_HELP_STRING([--enable-ssl], [build for ssl support (default is yes)])],
[if test "$enableval" = "yes"; then
AC_DEFINE([_SSL_SUPPORT_], [1], [Define if --enable-ssl])
MY_LDADD="-lACE_SSL"
else
MY_LDADD=""
fi
],
[AC_DEFINE([_SSL_SUPPORT_], [1], [Define if --enable-ssl])
MY_LDADD="-lACE_SSL"
])
从例子可以看出:
我们还需要几个简单的宏,帮我们将选项的一些值进行更进一步的处理
2.1.3 步骤三: 项目选项变量导出
测试结果或者选项结果的处理宏
2.1.3.1 定义C预处理器符号
在缺省状态下,AC_OUTPUT把由这些宏定义的符号放置到输出变量DEFS中,该变量为每个定义了的符号添加一个选项`-Dsymbol=value'。
AC_DEFINE (variable [, value [, description]])
AC_DEFINE_UNQUOTED (variable [, value [, description]])
类似于AC_DEFINE,但还要对variable和value进行三种shell替换(每种替换只进行一次):
变量扩展(`$'),命令替换(``'),以及反斜线传义符(`\')。
值中的单引号和双引号没有特殊的意义。在variable或者value是一个shell变量的时候用本宏代替AC_DEFINE
2.1.3.2 设置输出变量
记录测试结果的一种方式是设置输出变量,该变量是shell变量,它的值将被替换到configure输出的文件中。
AC_SUBST (variable, [value])
从一个shell变量创建一个输出变量。让AC_OUTPUT把变量variable替换到输出文件中(通常是一个或多个 `Makefile')。
这意味着AC_OUTPUT将把输入文件中的实例替换成调用AC_OUTPUT时shell变量variable的值。
variable的值不能包含新行。
ex:
AC_SUBST(LDADD, MY_LDADD)
AC_SUBST_FILE (variable)
另一种从shell变量创建输出变量的方式。
让AC_OUTPUT把由shell变量variable给出的文件名的文件的内容(不进行替换)插入到输出文件中。
这意味着AC_OUTPUT将在输出文件中(比如`Makefile.in')把输入文件中的实例
替换为调用AC_OUTPUT时shell变量variable的值指明的文件的内容。
如果没有文件可以插入,就把变量设置成`/dev/null'。
ex:
configure.ac文件:
AC_SUBST_FILE([host_frag])
host_frag=$srcdir/conf/sun4.mh
Makefile.in文件:
@host_frag@
2.1.4 步骤四: 项目文件输出设置
AC_CONFIG_FILES
配置输出文件
AC_CONFIG_HEADERS
配置输出头文件
AC_CONFIG_COMMANDS
配置输出命令
AC_CONFIG_LINKS
配置输出链接
以上四个宏的格式相同,如下:
AC_CONFIG_FILES (file . . . , [cmds], [init-cmds])
项目输出文件定义:
ex:
AC_CONFIG_FILES([Makefile, src/Makefile])
AC_OUTPUT
or
AC_OUTPUT([Makefile, src/Makefile])
2.2 编写Makefile.am
2.2.1 确定目录树结构
本文例子目录树结构:
project
|
|-- Makefile.am [项目根目录 Makefile.am]
|-- common[common子目录]
| |
| |---Makefile.am [项目子目录 Makefile.am]
| |
| |---test[test 子文件夹]
| |----Makefile.am [项目子目录测试子目录 Makefile.am]
|
|-- opt [opt子目录]
| |
| |---Makefile.am [项目子目录 Makefile.am]
| |
| |---test[test 子文件夹]
| |----Makefile.am [项目子目录测试子目录 Makefile.am]
|
|
|-- exe [exe子目录]
|
|---Makefile.am [项目子目录 Makefile.am]
|
|---test[test 子文件夹]
|----Makefile.am [项目子目录测试子目录 Makefile.am]
2.2.2 根目录Makefile.am编写
2.2.2.1 子目录递归
项目文件下的Makefile.am主要定义需要递归执行的子目录,通过SUBDIRS进行定义
SUBDIRS=common opt exe .
编译按照SUBDIRS的顺序进行,make clean则按相反的顺序进行。
2.2.2.2 子目录的条件执行
项目在编译的过程中,可能需要根据用户./configure 相关条件设置,设置有些目录不需要
进行编译。
例如:项目目录下opt目录作为一个可选项
子目录下test目录同样是一个可选项
方法一:通过 AM_CONDITIONAL 宏定义变量
configure.ac:
AM_CONDITIONAL([COND_OPT],[test "$want_opt" = "yes"])
AC_CONFIG_FILES([Makefile common/Makefile opt/Makefile exe/Makefile])
项目目录Makefile.am:
if COND_OPT
MAYBE_OPT = opt
endif
SUBDIRS = common $(MAYBE_OPT) exe .
注:
定义SUBDIRS只是对 make all有效, 会根据用户的设置判断是否需要进行opt目录编译。
如果使用 make dist 命令,则 所有子目录都会递归执行。
Automake 会自动定义 DIST_SUBDIRS = common opt exe .
方法二:通过AC_SUBST宏定义输出变量
configure.ac
if test "$want_opt" = yes; then
MAYBE_OPT=opt
else
MAYBE_OPT=
fi
AC_SUBST([MAYBE_OPT])
AC_CONFIG_FILES([Makefile common/Makefile opt/Makefile exe/Makefile])
项目目录Makefile.am:
SUBDIRS = common $(MAYBE_OPT) exe .
同理,对各子目录下test子目录,可以通过相似的办法设置,提示设置各子目录下的Makefile.am文件。
2.2.2.3 根目录设置环境变量
有些变量是从Autoconf中继承而来的;它们是CC、 CFLAGS、CPPFLAGS、DEFS、 LDFLAGS和LIBS
还有一些附加的变量是Automake自行定义的:
INCLUDES
一个`-I'选项的列表。如果你需要包含特殊的目录,你可以在你的`Makefile.am'中设置它。 automake已经自动地提供了一些`-I'选项。特别地,它生成`-I$(srcdir)'和一个指向保存了 `config.h'的目录的`-I'选项(如果你已经使用了AC_CONFIG_HEADER或者AM_CONFIG_HEADER)。 除了`-I'以外,INCLUDES实际上还可以用于添加任何cpp选项。例如,有时用它把任意的`-D'选项传递给编译器。
COMPILE
实际用于编译C源文件的命令。文件名被添加到它的后面以形成完整的命令行。
LINK
实际用于连接C程序的命令。
可用的全局变量:
INCLUDES=
LDADD=
LDFLAGS=
EXTRA_DIST=
2.2.3 子目录Makefile.am编写
要求:本例子中,将common子目录文件编译成libcmm.a,
将exe子目录文件编译成 project 执行文件
2.2.3.1 编译执行程序 (PROGRAMS)
步骤:
a. 定义程序名与程序源文件
程序可以被安装在以下目录 bindir, sbindir, libexecdir, pkglibdir, noinst [这些均是目录变量名];
根据自己的需要定义目录:
如, 程序安装在 bin 目录下,则定义程序时 格式如下:
bin_PROGRAMS=app1 app2 ...
b. 定义程序源文件
根据具体定义的程序名,定义各程序的源文件,如下:
app1_SOURCES= a.cpp b.cpp c.cpp ..
app2_SOURCES= x.c y.c z.c
如果Makefile.am中没有定义程序源文件, 系统按照默认 app_name.c 处理。
c. 定义程序需要的链接库
使用全局变量 LDADD 添加链接库
或者使用AM_LDFLAGS 变量设置链接库路径
AM_CPPFLAGS变量设置 编译选项
AM_LDFLAGS = -L.
AM_CPPFLAGS = -DINSTALL_DIR=\"$(prefix)\" -I.
AM_CXXFLAGS = -Wall
LDADD = -lACE -lcmm
---------------------------------------------------
[exe 子目录Makefile.am]
AM_LDFLAGS = -L../commom
AM_CPPFLAGS = -DINSTALL_DIR=\"$(prefix)\" -I../common
AM_CXXFLAGS = -Wall
#LDADD= -lACE from configure.ac
LDADD += -lcmm
bin_PROGRAMS = app
app_SOURCES=main.cpp
----------------------------------------------------
2.2.3.2 编译静态函数库
-----------------------------------------------------
[common 子目录Makefile.am]
SUBDIRS= . $(DIR_TEST)
AM_CPPFLAGS = -DINSTALL_DIR=\"$(prefix)\" -I.
AM_CXXFLAGS = -Wall
noinst_LIBRARIES = libcmm.a
libcmm_a_SOURCES=foo.cpp
------------------------------------------------------
------------------------------------------------------
[common 子目录 test 子目录 Makefile.am]
AM_LDFLAGS = -L../
AM_CPPFLAGS = -DINSTALL_DIR=\"$(prefix)\" -I../
AM_CXXFLAGS = -Wall
#LDADD= -lACE from configure.ac
LDADD += -lcmm
bin_PROGRAMS = test
test_SOURCES=test_cmm.cpp
------------------------------------------------------
2.2.3.2 编译共享库
3. 自定义autoconf宏
[待续]