evllib 合并静态库开发记录
1.纯净项目
2.autoscan 获取简单的 ./configure.in
3.在./configure.in 添加 AC_PROG_RANLIB 用以生成静态库
4.Makefile.am 内容为:
AUTOMAKE_OPTIONS=foreign SUBDIRS=linux event fixobjpool utility database noninst_LIBRARIES=libevllib.a noninstdir=/usr/lib/libevllib.a ACLOCAL_AMFLAGS=-I m4 #所有 宏添加到 m4 目录 libevllib_a_SOURCES=evllib_impl.cpp evlbuffer_impl.cpp libevllib_a_LIBADD=utility/libevlutility.la
5. aclocal
6.autoheader
7.autoconf
8.automake --add-missing
error & warning reported:
configure.in: no proper invocation of AM_INIT_AUTOMAKE was found. configure.in: You should verify that configure.in invokes AM_INIT_AUTOMAKE
需要在 configure.in 内添加 AM_INIT_AUTOMAKE:
###############################################
AC_PREREQ(2.68) AC_INIT([myevllib], [1.0]) AC_CONFIG_SRCDIR([evllib_impl.cpp]) AC_CONFIG_HEADER([config.h]) #check for programs. AC_PROG_CXX AC_PROG_CC AC_PROG_RANLIB #check for header files AC_CHECK_HEADERS([stdlib.h string.h]) #check for typedefs, structures, and compiler characteries AC_HEADER_STDBOOL AC_TYPE_SIZE_T #check for library functions AC_FUNC_MALLOC AC_CHECK_FUNCS([inet_ntoa memset select socket]) AC_CONFIG_FILES([Makefile database/Makefile event/Makefile fixobjpool/Makefile linux/Makefile utility/Makefile]) AC_OUTPUT
5. aclocal
6.autoheader
7.autoconf
8.automake --add-missing
error & warning reported:
utility/Makefile.am:3 Libtool library used but 'LIBTOOL' is undefined utility/Makefile.am:3 The usual way to define 'LIBTOOL' is to add 'AC_PROG_LIBTOOL'
在 configure.in 上添加 AC_PROG_LIBTOOL 以生成 utility/libevlutility.la 的 libtool 库:
###############################################
AC_PREREQ(2.68) AC_INIT([myevllib], [1.0]) AC_CONFIG_SRCDIR([evllib_impl.cpp]) AC_CONFIG_HEADER([config.h]) #check for programs. AC_PROG_CXX AC_PROG_CC # AC_PROG_RANLIB -----replaced with AC_PROG_LIBTOOL
AC_PROG_LIBTOOL +++++ new added #check for header files AC_CHECK_HEADERS([stdlib.h string.h]) #check for typedefs, structures, and compiler characteries AC_HEADER_STDBOOL AC_TYPE_SIZE_T #check for library functions AC_FUNC_MALLOC AC_CHECK_FUNCS([inet_ntoa memset select socket]) AC_CONFIG_FILES([Makefile database/Makefile event/Makefile fixobjpool/Makefile linux/Makefile utility/Makefile]) AC_OUTPUT
5. aclocal
因为使用了 LIBTOOL 输出了很多 版本兼容相关的warning 和 过程输出。
6.autoheader
7.autoconf
8.automake --add-missing
error & warning reported:
configure.in: 14 required file './ltmain.sh' not found
暂不理, 看再一次autoconf 能否生成
9.autoconf
10../configure
error & warning reported:
sed: can't read ./ltmain.sh: No sush file or directory
但是 ltmain.sh 是什么呢? 有什么用?先得看 configure 的生成过程:
aclocal:
autoheader:
automake & libtoolize:
autoconf:
看得出 ltmain.sh 和 ltconfig是在 libtoolize 时生成的, 但是 libtoolize有什么用处呢?
前面的 aclocal.m4 是 根据 用户修改的 configure.in 生成的中间 文件, 最终用于生成 configure
其实是 对 configure.in内各种 宏的 展开,以及一些其他文件、变量的加入;而对于 libtool, 他的正确使用也需要一些相关的设置, 需要自己的各种宏 ,例如
libtool.m4
ltoptions.m4
ltversion.m4
lt~obsolete.m4
ltsugar.m4
libtool 所需这些宏及其相关文件是通过 libtoolize 生成的, 估计 ltmain.sh 和 ltconfig 都是 必须的文件, 现在这些宏 应该如何导入? 其实也可以在 configure.in文件内, 一种方法在 configure.in 内仔细修改, 一种是 直接拷贝 默认的 libtool.m4 到当前目录,第三种是使用 一个特定的 包含这些宏相关文件的 目录。为了让环境清洁, 这里采用第三种独立文件夹 m4 方式。这是我们是否可以讲 libtoolize 和 aclocal 做个类比:
configure.in ====> aclocal ====> aclocal.m4
configure.in ====>libtoolize ====> libtoolize所需 m4
第一如果 在configure.in 没有显示指明 AC_CONFIG_MACRO_DIR 目录, 在进行 libtoolize 时会在 根目录下(其实是configure.in相同目录先生成相关的 文件), 否则会在 AC_CONFIG_MACRO_DIR 指定的目录生成一些文件, 于是我的configure.in修改成:
AC_PREREQ(2.68) AC_INIT([myevllib], [1.0]) AC_CONFIG_SRCDIR([evllib_impl.cpp]) AC_CONFIG_HEADER([config.h]) AC_CONFIG_MACRO_DIR([m4]) +++++ new added #check for programs. AC_PROG_CXX AC_PROG_CC # AC_PROG_RANLIB -----replaced with AC_PROG_LIBTOOL AC_PROG_LIBTOOL +++++ new added #check for header files AC_CHECK_HEADERS([stdlib.h string.h]) #check for typedefs, structures, and compiler characteries AC_HEADER_STDBOOL AC_TYPE_SIZE_T #check for library functions AC_FUNC_MALLOC AC_CHECK_FUNCS([inet_ntoa memset select socket]) AC_CONFIG_FILES([Makefile database/Makefile event/Makefile fixobjpool/Makefile linux/Makefile utility/Makefile]) AC_OUTPUT
但同时, 我在 Makefile.am 内也添加了 m4 目录的指定:
AUTOMAKE_OPTIONS=foreign SUBDIRS=linux event fixobjpool utility database noninst_LIBRARIES=libevllib.a noninstdir=/usr/lib/libevllib.a ACLOCAL_AMFLAGS=-I m4 #所有 宏添加到 m4 目录 ------- here libevllib_a_SOURCES=evllib_impl.cpp evlbuffer_impl.cpp libevllib_a_LIBADD=utility/libevlutility.la
5. aclocal
6.autoheader
7.libtoolize --copy --force
成功拷贝 libtool 所需的各种默认 .m4 文件到 m4 目录
8.autoconf
9.automake --add-missing
10../configure
11.make
成功生成 ./utiliby/libevlutility.la 和 ./libevllib.a
但是 nm libevllib.a 时还是 只能看到 libevlutility.la 而非具体的 o文件
###############################################
尝试不使用 libtool 的 convenience library .la , 而直接生成普通的 静态库 .a
大不了使用 ar , ranlib 直接手工活的 .o 最后合并成 .a
那么 utility/Makefile.am 将如
AUTOMAKE_OPTIONS=foreign noninst_LIBRARIES=libevlutility.a noninstdir=$(EVLLIB_SRC_TOP_DIR)/utility/ libevlutility.a_SOURCES=variant.cpp readConfig.cpp
根目录 $(EVLLIB_SRC_TOP_DIR)的Makefile.am 将如:
AUTOMAKE_OPTIONS=foreign SUBDIRS=linux event fixobjpool utility database noninst_LIBRARIES=libevllib.a # noninstdir=/usr/lib/libevllib.a -------------- modifyed noninstdir=$(EVLLIB_SRC_TOP_DIR) ACLOCAL_AMFLAGS=-I m4 #所有 宏添加到 m4 目录 ------- here libevllib_a_SOURCES=evllib_impl.cpp evlbuffer_impl.cpp libevllib_a_LIBADD=./utility/libevlutility.a
5. aclocal
6.autoheader
7.libtoolize --copy --force
成功拷贝 libtool 所需的各种默认 .m4 文件到 m4 目录
8.autoconf
9.automake --add-missing
10../configure
11.make
这样能够生成 出最终的 libevllib.a
并且其内部包含了如何下文件:
evllib_impl.o
evlbuff_impl.o
libevlutility.a
将其他所需的源合并后, 将如:
evllib_impl.o
evlbuff_impl.o
libevlutility.a
libdatabase.a
libfixobjpool.a
libevllinux.a
###############################################
为了将上传输的 所有 .o 和 .a 文件合并到 单一的一个 静态库 libevllib.a (注意这里的 libevllib.a 名字是相同的), 在根目录下 添加了一个 目录 ./targetDir/ 用以处理ar 的解包 和 合并静态库; 在添加一个自动脚本 ./artest 用以在 targetDir 内完成全部工作:
#!/bin/bash
# 从根目录 移动 libevllib.a 到 工作目录 targetDir, 此时只有一个 静态库 libevllib.a 哟 echo moving libevllib.a into targetDir mv ./libevllib.a ./targetDir/
# 进入 工作目录 targetDir echo entering targetDir... cd targetDir
# 接下来是一个循环,使用 ar -x 解压出 各种 静态库文件.a 的内容后, 还需要对新文件进行.a 查找并解压,
# 因为 可能 一个 .a 文件内包含有其他的 .a 文件, 就如本例的 libevllib.a
echo loop finding and exploding orignal static files...
#fineshed 是全部 .a 被解压成功标记 finished=0; until [[ $finished == 1 ]]; do
#查找所有.a 文件 filelist=`ls | grep '.a\>' ` if [ "$filelist" != "" ]; then echo files found: $filelist
#逐个解压 .a 文件, 并 移除 for file in $filelist do echo expanding $file ar -x $file echo deleting $file rm -f $file done else finished=1 echo all orignal static file dealed. fi done;
#将全部解压出来的 .o 文件 合并成一个静态库 文件 libevllib.a echo generating target file libevllib.a ... ar rcs libevllib.a *.o
#一些移动操作 echo coping libevllib.a to /usr/lib/ cp ./libevllib.a /usr/lib/ echo leaving targetDir... cd ../ echo done.
最后 $./artest
即可生成所需文件
文章参考:
C1.aclocal : http://www.sourceware.org/autobook/autobook/autobook_277.html#SEC277
C2.autoheader: http://www.sourceware.org/autobook/autobook/autobook_278.html#SEC278
C3.automake & libtoolize :http://www.sourceware.org/autobook/autobook/autobook_279.html#SEC279
C4.autoconf : http://www.sourceware.org/autobook/autobook/autobook_280.html#SEC280
Invoking libtoolize : http://www.gnu.org/software/libtool/manual/html_node/Invoking-libtoolize.html
GNU的ar,ranlib和nm: http://blog.sina.com.cn/s/blog_4fcd1ea30100uu3m.html