简介
每次运行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中
mv aclocal.m4 acinclude
aclocal
autoconf然后写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