简介
每次运行automake,它都用调用autoconf来解析configure.ac,获取一些宏,产生合适的Makefile.in.本文主要介绍configure.ac一些重要的宏
每次运行aclocal,它都会扫描所有的.m4文件寻找宏定义,然后再扫描configure.ac
编译相关宏
定义程序源文件
bin_PROGRAMS = hello
hello_SOURCES = hello.c version.c getopt.c getopt.h systerm.h
- 任何以.c结尾的文件都会被编译为相应的.o, 最后会被链接为
hello
; - 如果
hello_SOURCES
没有被定义,则默认为hello.c
; - 列在
_SOURCES
中的头文件会被部署,否则不会;
条件编译
如果hello-linux.c
或者hello-generic.c
按条件参与hello
的编译,则相应的Makefile.am
如下
bin_PROGRAMS = hello
hello_SOURCES = hello-common.c
EXTRA_hello_SOURCES = hello-linux.c hello-generic.c
hello_LDADD = $(HELLO_SYSTEM)
hello_DEPENDENCIES = $(HELLO_SYSTEM)
则在configure.ac
中对应如下
...
case $host in
*linux*) HELLO_SYSTEM='hello-linux.$(OBJEXT)';;
*) HELLO_SYSTEM='hello-generic.$(OBJEXT)';;
esac
AC_SUBST([HELLO_SYSTEM])
...
- 在上面的例子中,
HELLO-SYSTEM
将会被hello-linux.o
或者hello-generic.o
所替代
当然也可以选择条件编译来代替EXTRA_
前缀,Automake会检测变量值来构建合适的编译依赖
bin_PROGRAMS = hello
hello_SOURCES = hello-common.c
if LINUX
hello_SOURCES +=hello-linux.c
else
hello_SOURCES += hello-generic.c
endif
在编译GNU的cpio
时,在不同环境下编译工具会选择mt
或者rmt
来参与编译,这时有两种方法来进行编译
- 替代编译
- 条件编译
替代编译:
bin_PROGRAMS = cpio pax $(MT)
libexec_PROGRAMS = $(RMT)
EXTRA_PROGRAMS = mt rmt
由于Automake会自动增加$(EXEEXT)
后缀重写bin_PROGRAMS
,libexec_PROGRAMS
,EXTRA_PROGRAMS
,这时切记要使用AC_SUBST([MT],['mt$(EXEEXT)'])
条件编译:
bin_PROGRAMS = cpio pax
if WANT_MT
bin_PROGRAMS += MT
endif
if WANT_RMT
bin_PROGRAMS +=rmt
endif
这种方式就不用担心$(EXEEXT)
后缀。
编译静态库
使用libtool及LTLIBRARIES
编译共享库,将会被安装在libdir
或者pkglibdir
目录
例如要编译一个libcpio.a
,但是不安装它,可以如下:
noinst_LIBRARIES = libcpio.a
libcpio_a_SOURCES = ...
libcpio_a_LIBADD = $(LIBOBJS) $(ALLOCA)
编译静态库只需要编译所有的有效文件,然后使用ar
工具进行链接,$(AR)
及$(ARFLAGS)
为Makefile.am
中对应的预设变量;最后对静态库使用$(RANLIB)
来更新符号表.对于这些变量的设置,一般有四种不同方法:
- 在configure.ac中定义
AC_PROG_RANLIB
- 在configure.ac中定义
AM_PROG_RANLIB
- 在Makefile.am中直接设置变量
RANLIB
的值 - 在configure.ac使用
AC_SUBST
来设置变量值
下面这个小例子中,程序cpio
静态链接了libcpio.a
noinst_LIBRARIES = libcpio.a
libcpio_a_SOURCES = ...
bin_PROGRAMS = cpio
cpio_SOURCES = cpio.c ...
cpio_LDADD = libcpio.a
编译动态库
由libtool
工具编译出的文件被称为libtool文件
,他们一般由.lo
或者.la
为后缀,automake使用libtool编译共享库要以LTLIBRARIES
为主标志,每一个_LTLIBRARIES
变量都是一系列要编译的libtool共享库
lib_LTLIBRARIES = libgettest.la
libgettest_la_SOURCES = gettext.c gettext.h ...
- 首先在linux中使用libtool前要先运行
libtoolize
- 如果
gettext.h
是一个要供大家使用的库函数,则需要使用_HEADERS
变量 - 申明在
libgettest_la_SOURCES
中的库函数是内部使用的接口
下面这个例子编译了一个程序hello
,链接了libgettext.la
lib_LTLIBRARIES = libgettest.la
libgettext_la_SOURCES = gettext.c
bin_PROGRAMS = hello
hello_SOURCES = hello.c ...
hello_LDADD = libgettext.la
hello
是静态还是动态链接libgettext.la
是未知的,由libtool的配置及主机配置决定.
条件编译libtool libraries
两种不同情况
-
Automake 条件编译
对于在automake运行阶段,目的地址已经知道,automake会自动提供合适的`-rpath`选项给`libtool`,这种情况一般用于库文件已经显示的罗列在了`_LTLIBRARIES`上
-
autoconf的AC_SUBST置换
对于在运行`./configure`时,才被决定的库文件(`EXTRA_LTLIBRARIES`),这种情况,automake并不清楚最后的安装地址,这时,对于`_LDFLAGS`必须增加合适的`-rpath`参数.
EXTRA_LTLIBRARIES = libfoo.la libbar.la
lib_LTLIBRARIES = $(WANTEDLIBS)
libfoo_la_SOURCES = foo.c ...
libfoo_la_LDFLAGS = -rpath '$(libdir)'
libbar_la_SOURCES = bar.c ...
libbar_la_LDFLAGS = -rpath '$(libdir)'
lib_LTLIBRARIES =
if WANT_LTBFOO
lib_LIBRARIES +=libfoo.la
endif
if WANT_LTBBAR
lib_LTLIBRARIES +=libbar.la
endif
libfoo_la_SOURCES = foo.c ...
libbar_la_SOURCES = bar.c ...
如果你有自己的m4宏,即aclocal.m4,可以重命名为acinclude.m4,则会自动被包含进aclocal.m4中
然后写Makefile.am,告诉automake要生成什么,怎么生成
主目录中的Makefile.am
SUBDIRS = src
dist_doc_DATA = README
src
目录中的Makefile.am
bin_PROGRAMS = hello
hello_SOURCES = main.c
hello_LDADD = $(LIBOBJS)
再运行
autoheader
automake --add-missing
也可以在编写完configure.ac
及Makefile.am
后直接运行
autoreconf
源代码下载:
git clone git@github.com:pzh2386034/automakeLearnExample.git