Autoconf/Automake/libtool的使用例子
现在有环境 t/,下面有4个源码目录分别是client/ lib/ daemon/ module/,要达到的目标是
1、将lib/ module/ daemon/ 一起编译,编成可执行文件 mydaemon
2、将 lib/ client/ 一起编译,编成动态库libmylib.so
3、将 lib/ client/ 一起编译,与目标2不同的是,在编译client/下的源文件时要带上预编译-D__DEBUG_MAIN__选项,最后编译成test1、test2、test3、test4,这个功能常用来生成一个测试的程序或工具。
4、make all要求把以上3个目标都编译出来,make install的时候只安装mydaemon和libmylib.so
5、除了常见make all和make install以外,增加make newiled make libnewfile.so make 以及make install-newfiled make install-libnewfile 。
步骤如下:
1、确保机器上安装以下软件 aclocal autoconf libtoolize automake 。编写一个脚本init.sh,把以下程序的加进去,如下:
touch NEWS
touch README
touch AUTHORS
touch ChangeLog
aclocal
autoconf
libtoolize --force --automake --copy
automake --copy --add-missing --gnu
2、通过autoscan生成configure.ac,然后将它改名configure.in,然后作如下几处修改。
a、AC_INIT(mysoft,1.0,xxx@163.com)
b、AC_INIT_AUTOMAKE(mysoft,1.0)
c、AC_PREFIX_DEFAULT(/usr/local/mysoft) 这里添上安装文件的路径,比如/usr/local/mysoft/
d、增加LIBTOOL=”$LIBTOOL --silent”
e、AC_OUTPUT(Makefile lib/Makefile client/Makefile module/Makefile daemon/Makefile) 这里列出你要生成的全部的Makefile。
3、这步是关键,为每个目录添加一个叫Makfile.am的文件,具体如下:
a、在t/目录下,由于这个目录下本身没有源文件(源文件都在它的子目录里面),所以这个目录下的Makefile..am很简单,只要写下面一句
SUBDIRS lib module client daemon
注意编译时的先后次序。
b、在lib/目录下,由于这个目录下的源文件是为其它目录的源文件服务的,所以在lib目录下,我们编译出一下.a文件,以供别的目录使用。在Makefile.am中写如下内容:
noinst_LIBRARIES = libcompat.a
libcompat_a_SOURCES = a.c b.c c.c d.c
libcompat_a_CFLAGS = -I../include -I/usr/local
noinst_LIBRARIES的意思是生成的库是不会被make install 所安装的。库的名字可以随便取。
libcompat_a_CFLAGS是编译时要带的一些选项
c、module/目录和功能和lib/的功能相似,因此Makefile.am也相似,如下
noinst_LIBRARIES = libmodule.a
libmodule_a_SOURCES = a.c b.c c.c d.c
libmodule_a_CFLAGS = -I../daemon -I.../include
d、client目录的Makefile.am较复杂,因为1:它要完成目标2,编译出一个动态库。2:它又要完成目标3,编译出一些可执行文件出来。
LDADD = ../lib/libcompat.a
AM_CFLAGS = -D__DEBUG_MAIN__ -I../include -I../usr/local/include
AM_LDFLAGS = -lpthread –lssl –L/usr/local/lib
(LDADD指的是编译这个目录的时候,会用到这个.a。AM_CFLAGS是全局的选项,当某个程序prog有prog_CFLAGS时,AM_CFLAGS会被替换掉。)
noinst_PROGRAMS = test1 test2 test3 test4
(因为在目标4中要求make install的时候不安装这些程序,所以是noinst。
这里没有指明编译这些程序的源文件,所以默认会去找test1.c test2.c test3.c test4.c
这里没有指明编译选项,所以在编译这些程序时,会使用AM_CFLAGS。)
lib_LTLIBRARIES = libmylib.la
libmylib_la_SOURCE = a.c b.c c.c d.c
libmylib_la_LDFLAGS = -lpthread
libnewfile_la_CFLAGS = -I../include
include_HEADERS = ../include/mylib.h
(lib_LTLIBRARIES 是说明要生成的动态库名称,因为是使用libtool,所以这里用的是la,生成动态库的过程由libtool去自动完成。 libmylib_la_LDFLAGS说明的是要连接的时候用到的一些库,libnewfile_la_CFLAGS是在编译libmylib.la时用到的选项。include_HEADERS是指在安装libmylib时,要把这个头文件也安装到include里面)
e、daemon/目录。将如下内容写到Makefile.am中
LDADD = ../module/libmodule.a ../lib/libcompat.a
libexec_PROGRAMS = mydaemon
mydaemon_SOURCES = a.c b.c c.c d.c e.c
mydaemon_CFLAGS = -I../include
mydaemon_LDFLAGS = -lpthread –L/usr/local/lib
(libexec_PROGRRAMS, 指的是要生成的程序名,并且暗示程序安装的路径,这里用的是libexec_ 原因是mydaemon是一个daemon,按照freebsd上的通用做会是把daemon放在libexec/下。同理,如果你写成bin_PROGRRAMS,程序会被安装到bin/)。
f、到目前为止, init.sh应该可以远行了,然后./configure 然后make all make install。但还没有完成我们全部的任务,因为还有最后一个目标5,为了增加make的target,我们的作法是直接在最顶部目录t/Makefile.am中按照Makefile的写法,手工增加 target。之所以可以这样做有两个原因,第一、是因为automake自动会把Makefile.am的内容原封不动地拷到新生成的Makefile 中,所以在Makefile.am中增加target也就相当于在新生成的Makefile中增加。第二、在默认情况下,Makefile.am中的每个要生成的程序都可以在相应目录中单独去make,也就是说automake会为每个要生成的程序写一个target。比如在client目录中,我们可以 make test1 make libmylib,这些都可以成功执行。
知道了上述两个原因,我们就可以开始修改t/Makefile.am,增加下列内容:
mydaemon: lib/*.c module/*.c daemon/*.c
$(MAKE) –C lib
$(MAKE) –C module
$(MAKE) mydaemon –C daemon
libmylib: lib/*.c client/*.c
$(MAKE) –C lib
$(MAKE) libmylib.la –C client
test: lib/*.c client/*.c
$(MAKE) –C lib
$(MAKE) test1 –C lib
$(MAKE) test2 –C lib
$(MAKE) test3 –C lib
$(MAKE) test4 –C lib
install-libmylib: client/libmylib.la
$(mkinstalldirs) $(libdir)
$(LIBTOOL) --mode=install /usr/local/install -c client/libmylib.la $(libdir)/libnewfile.la
install-test: client/*.c
$(mkinstalldirs) $(bindir)
$(LIBTOOL) --mode=install /usr/local/install –c client/test1 $(bindir)/test1
$(LIBTOOL) --mode=install /usr/local/install –c client/test2 $(bindir)/test2
$(LIBTOOL) --mode=install /usr/local/install –c client/test3 $(bindir)/test3
$(LIBTOOL) --mode=install /usr/local/install –c client/test4 $(bindir)/test4
install-mydaemon daemon/mydaemon
$(mkinstalldirs) $(DESTDIR)$(libexecdir)
$(LIBTOOL) --mode=install /usr/bin/install –c daemon/mydaemon $(libexecdir)/mydaemon
($(mkinstalldirs) $(libexecdir)的作用是看看有没有这个目录,如果没有的话新建。$(libexecdir)就是/usr/local/mysoft/libexec/。)
到此为止,任务完成了。运行./init.sh ,运行./configure,它会根据Makefile.am生成Makefile,然后就可以make 以及make install了。
总结一下:
1、两个很有用的选项 prog_CFLAGS prog_LDCFLAGS 可以满足我们增加编译选项和连接选项的功。对应的全局变量是AM_CFLAGS AM_LDFLAGS
2、如果是两个或两个以上目录的源文件需要合在一起编译,可以采用每个目录编译编译成一个.a,然后能过LDADD把它们放在一起连接。
3、我们可以直接在Makefile.am中写Makefile的内容。
我在做的过程序中疑惑的问题
1、当bin_PROGRAMS=hello hello_SOURCE=test1.c test2.c时,AutoMake生成的中间文件会是hello-test1.o hello-test2.o,看起来有点别扭。
2、有时明明是我只修改了Makefile.am,按理说,我只要执行./configure,就可重新生成Makfile。但有时并不能如我所愿,而我重新执行./init.sh问题就解决了。我的经验是当你修改了Makefile.am后发现没什么变化的时候,运行一下./init.sh或许就好了。
3、在使用过程中觉得make好像有什么记忆之类的机制,有时,我改了Makfile.am,重新生成了Makefile后,运行make,它还是上次运行失败的结果,再运行一次就好了。很奇怪。
4、我在编辑Makefile.am时,往Makefile.am里面增加command的,我在command 前面明明是用了/t,可是最终被 Automake拷到新的Makefile后,却变成了4个空格。很郁闷,最后用了一个笨方法,把Makefile.am改名成Makefile,用vi 打开看一下,确保是/t,然后再把名字改回去。这样就可以了,可能是我vim的配置问题。
转于
阅读(1062) | 评论(0) | 转发(1) |