Networking /C++/Linux

  C++博客 :: 首页 :: 联系 :: 聚合  :: 管理
  11 Posts :: 14 Stories :: 1 Comments :: 0 Trackbacks

常用链接

留言簿(4)

我参与的团队

搜索

  •  

最新评论

阅读排行榜

评论排行榜

用automake建立共享库(动态链接库)Makefile

要使用automake工具包建立一个交叉编译的共享库的Makefile

这里用的autoconf是2.67版本,在debian下实现:

如果版本低,可以用apt-get install automake来装最新的版本,还需要libtool,也需要用apt-get install来安装。

这里建立一个简单的函数库来介绍:

建立目录rx,及源码目录src:

$mkdir rx
$mkdir rx/src

在rx/src下编辑rx.c,rx.h两个源文件:

mybdebian:/home/myb/php/rx/src# cat rx.h
#ifndef __RX_H_
#define __RX_H_
int fun
();
#endif
mybdebian:
/home/myb/php/rx/src# cat rx.c
#include "rx.h"
int fun
()
{
return 1234;
}

在rx目录和rx/src目录下分别建立Makefile.am文件

rx目录下的Makefile.am为顶层Makefile.am文件,只要包含其存放源码的子目录即可,内容如下:

AUTOMAKE_OPTIONS=foreign
SUBDIRS
=src

rx/src目录下的Makefile.am内容如下:

AUTOMAKE_OPTIONS=foreign
lib_LTLIBRARIES
=librx.la
librx_la_SOURCES
=rx.c
include_HEADERS=rx.h

其中lib_LTLIBRARIES=后面的“librx.la”为要生成的库文件名,必须写成.la,不能是.so,实际会生成librx.so文件。

下面的librx_la是librx.la把“.”换成下划线“_”后面加上“_SOURCES=”,等号以后为源文件名称,多于一个时用空格隔开。

include_HEADERS=后面的为头文件,是供其它程序包含用的,make install时会复制到安装目录的include 目录中。

回到上层目录,使用autoscan扫描源码目录:

$autoscan
$ls
autoscan.log configure.scan Makefile.am src

把configure.scan改名成为configure.ac

$mv configure.scan configure.ac
AC_OUTPUT([Makefile
src
/Makefile])

编译这个文件:

$vim configure.ac
# -*- Autoconf -*-
#
Process this file with autoconf to produce a configure script.

AC_PREREQ([
2.67])
AC_INIT([FULL
-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS])
AC_CONFIG_SRCDIR([src
/rx.c])
AC_CONFIG_HEADERS([config.h])

# Checks for programs.
AC_PROG_CC

# Checks for libraries.

# Checks for header files.

# Checks for typedefs, structures, and compiler characteristics.

# Checks for library functions.

AC_CONFIG_FILES([Makefile
src
/Makefile])
AC_OUTPUT

修改AC_INIT一句,即把包的全名、版本号及BUG报告email地址添上,如:

AC_INIT(rx2dlib,0.01,resound@163.com)

在它后面加一句:

AM_INIT_AUTOMAKE

这句话是必须的。

由于这个脚本是用于生成共享库的,所以要加一句AC_PROG_LIBTOOL在AC_PROG_CC的下一行:

# Checks for programs.
AC_PROG_CC
AC_PROG_LIBTOOL

修改后面的那个AC_CONFIG_FILES语句,改成AC_OUTPUT,并把后面的一条AC_OUTPUT去掉:

AC_OUTPUT([Makefile
src
/Makefile])

这样,configure.ac就建好了,修改后的内容如下:

# -*- Autoconf -*-
#
Process this file with autoconf to produce a configure script.

AC_PREREQ([
2.67])
AC_INIT(rx2dlib,
0.01,resound@163.com)
AM_INIT_AUTOMAKE

AC_CONFIG_SRCDIR([src
/rx.c])
AC_CONFIG_HEADERS([config.h])

# Checks for programs.
AC_PROG_CC
AC_PROG_LIBTOOL

# Checks for libraries.

# Checks for header files.

# Checks for typedefs, structures, and compiler characteristics.

# Checks for library functions.

AC_OUTPUT([Makefile
src
/Makefile])

然后按顺序执行:

$aclocal
$autoconf
$autoheader
$libtoolize --automake
$automake –-add-missing
configure
.ac:13: installing `./config.guess'
configure
.ac:13: installing `./config.sub'
configure
.ac:6: installing `./install-sh'
configure
.ac:6: installing `./missing'
src
/Makefile.am: installing `./depcomp'

这时configure脚本已经生成了。

可以用它来配置生成Makefile了。

如我们要生成交叉编译给ARM CPU使用的共享库,这里假设我们要使用的编译器为arm-none-linux-gnueabi-gcc,并且我们最终在ARM板上执行时,要把库安装到目标板的/usr/local/armrx2d目录中去。可以这样配置:

$./configure --host=arm-none-linux-gnueabi --prefix=/usr/local/armrx2d

$make


Make完成后可以到src目录下面的一个隐藏目录.libs目录中看到生成的库文件:

mybdebian:/home/myb/php/rx/src/.libs# ls -l
总计
20
-rw-r--r--
1 root root 2368 04-19 22:48 librx.a
lrwxrwxrwx
1 root root 11 04-19 22:48 librx.la -> ../librx.la
-rw-r--r--
1 root root 930 04-19 22:48 librx.lai
lrwxrwxrwx
1 root root 14 04-19 22:48 librx.so -> librx.so.0.0.0
lrwxrwxrwx
1 root root 14 04-19 22:48 librx.so.0 -> librx.so.0.0.0
-rwxr-xr-x
1 root root 5422 04-19 22:48 librx.so.0.0.0
-rw-r--r--
1 root root 2228 04-19 22:48 rx.o

我们再回到顶层目录,执行make install可以自动安装生成的库到/usr/local/armrx2d/lib目录下。

若使用automake时出现下面错误信息

required file `./ltmain.sh' not found

是因为libtool未配置:

解决办法:

$libtoolize --automake --debug --copy –force

或:

$libtoolize --automake

#
#
# 利用libtool自动生成动态库
#
1. autoscan命令在当前目录生成configure.scan文件, 内容为:
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.57)
AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS)
AC_CONFIG_SRCDIR([src/bot.h])
AC_CONFIG_HEADER([config.h])
# Checks for programs.
AC_PROG_CXX
AC_PROG_CC
# Checks for libraries.
# Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS([limits.h malloc.h stdlib.h string.h unistd.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_HEADER_STDBOOL
AC_C_CONST
AC_C_INLINE
# Checks for library functions.
AC_FUNC_MALLOC
AC_FUNC_REALLOC
AC_CHECK_FUNCS([memset strcasecmp strchr strdup])
AC_OUTPUT
将其该名为configure.ac 然后修改:
configure.ac 文件是 autoconf 的输入文件,经过 autoconf 处理,展开里面的 m4宏,
输出的是 configure 脚本。
第 4 行声明本文件要求的 autoconf 版本,因为本例使用了新版本 2.57,所以在此注明。
第 5 行 AC_INIT 宏用来定义软件的名称和版本等信息
AC_INIT([test], 1.0, [email]linhanzu@gmail.com[/email])
增加版本信息(为生成lib库做准备)
lt_major=1
lt_age=1
lt_revision=12
dist_version=0.1.12
AM_INIT_AUTOMAKE(test, $dist_version) //自动生成Makefile文件
增加宏, 打开共享库
AC_PROG_LIBTOOL
# Check for dl  
DL_PRESENT=""
AC_CHECK_LIB( dl, dlopen, DL_PRESENT="yes",, $DL_LIBS -ldl )
if test "x$DL_PRESENT" = "xyes"; then
AC_DEFINE(HAVE_LIBDL, 1, [Define if DL lib is present])
DL_LIBS="-ldl"
AC_SUBST(DL_LIBS)
fi
# Check for libm
M_PRESENT=""
AC_CHECK_LIB( m, sin, M_PRESENT="yes",, $M_LIBS -lm )
if test "x$M_PRESENT" = "xyes"; then
AC_DEFINE(HAVE_LIBM, 1, [Define if libm is present])
M_LIBS="-lm"
AC_SUBST(M_LIBS)
fi
增加依赖库,这里就仅仅列举了pthread库,生成的Makefile会自动加上-pthread
# Check for pthread
PTHREAD_PRESENT=""
AC_CHECK_LIB( pthread, pthread_create, PTHREAD_PRESENT="yes",, $PTHREAD_LIBS
-lpthread )
if test "x$PTHREAD_PRESENT" = "xyes"; then
AC_DEFINE(HAVE_LIBPTHREAD, 1, [Define if libpthread is present])
PTHREAD_LIBS="-lpthread"
AC_SUBST(PTHREAD_LIBS)
fi
要生成项目工程目录和其它目录下的Makefile 文件, 必需加入
AM_CONFIG_FILES的宏:
例如: AC_CONFIG_FILES([Makefile
                     src/Makefile
                     data/Makefile
                     docs/Makefile])
修改完后Makefile.ac如下:
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.57)
AC_INIT([test],[1.0],[[email]arne_caspari@users.sourceforge.net[/email]])
AM_CONFIG_HEADER(config.h)
lt_major=1
lt_age=1
lt_revision=12
dist_version=0.1.12
AM_INIT_AUTOMAKE(test, $dist_version)
AC_SUBST(lt_major)
AC_SUBST(lt_revision)
AC_SUBST(lt_age)
# Checks for programs.
#AC_PROG_CC
#AC_PROG_INSTALL
#AC_PROG_LN_S
#AC_PROG_LIBTOOL
AM_PROG_LIBTOOL
# Checks for libraries.
pkg_modules="gtk+-2.0 >= 2.0.0"
PKG_CHECK_MODULES(GTK_PACKAGE, [$pkg_modules], HAVE_GTK2="yes", HAVE_GTK2="no" )
AC_SUBST(GTK_PACKAGE_CFLAGS)
AC_SUBST(GTK_PACKAGE_LIBS)
# Check for dl
DL_PRESENT=""
AC_CHECK_LIB( dl, dlopen, DL_PRESENT="yes",, $DL_LIBS -ldl )
if test "x$DL_PRESENT" = "xyes"; then
AC_DEFINE(HAVE_LIBDL, 1, [Define if DL lib is present])
DL_LIBS="-ldl"
AC_SUBST(DL_LIBS)
fi
# Check for libm
M_PRESENT=""
AC_CHECK_LIB( m, sin, M_PRESENT="yes",, $M_LIBS -lm )
if test "x$M_PRESENT" = "xyes"; then
AC_DEFINE(HAVE_LIBM, 1, [Define if libm is present])
M_LIBS="-lm"
AC_SUBST(M_LIBS)
fi
# Check for pthread 
PTHREAD_PRESENT=""
AC_CHECK_LIB( pthread, pthread_create, PTHREAD_PRESENT="yes",, $PTHREAD_LIBS
-lpthread )
if test "x$PTHREAD_PRESENT" = "xyes"; then
AC_DEFINE(HAVE_LIBPTHREAD, 1, [Define if libpthread is present])
PTHREAD_LIBS="-lpthread"
AC_SUBST(PTHREAD_LIBS)
fi
# Checks for header files.
#AC_HEADER_DIRENT
#AC_HEADER_STDC
#AC_CHECK_HEADERS([fcntl.h stdlib.h string.h sys/time.h unistd.h])
# Checks for typedefs, structures, and compiler characteristics.
#AC_TYPE_PID_T
#AC_TYPE_SIZE_T
#AC_HEADER_TIME
# Checks for library functions.
#AC_FUNC_CLOSEDIR_VOID
#AC_FUNC_MALLOC
#AC_CHECK_FUNCS([memset strstr])
AC_CONFIG_FILES([Makefile
             src/Makefile
             data/Makefile
             doc/Makefile])
AC_OUTPUT

2.生成各目录下的Makefile.am文件
./Makefile.am   //工程目录下
  SUBDIR = src data doc
../src/Makefile.am  //源码目录下
  MAINTAINERCLEANFILES = Makefile.in
   INCLUDES = -I../include  
   CPPFLAGS=-DINSTALL_PREFIX="\"$(prefix)\""
   lib_LTLIBRARIES = libtest.la
   libtest_la_LDFLAGS = -version-info @lt_major@:@lt_revision@:@lt_age@
   libtest_la_SOURCES = \
                      test.c \
                      test_private.h \
                      check_match.c \
                      check_match.h \
                      test_helpers.c \
                      test_helpers.h \
                      debug.h
    libtest_la_LIBADD = \
                      @DL_LIBS@ \
                      @M_LIBS@

3. 生成autogen.sh脚本, 内容
#! /bin/sh
set -x
aclocal
autoheader
automake --foreign --add-missing --copy
autoconf

保存后修改权限 chmod a+x autogen.sh

3.运行脚本./autogen.sh, 生成configure脚本. 这里可能会遇到错误, 可以根据错误提示作相应修改.(注意:如果您修改了Makefile.am中的项,那么就得重新执行这一步)

4.运行./configure脚本.自动生成src目录下的makefile文件

5. 切换到目录src, 运行make 自动在当前目录下建立.libs文件, 编程生成的库文件就保存在该目录下.
    make install 安装在默认目录 /usr/local/lib/下.

6.如果要生成其它的安装目录,Makefile.am就要这样写
MAINTAINERCLEANFILES = Makefile.in
INCLUDES = -I../include 
lib_LTLIBRARIES = libtt.la
libdir = $(prefix)/lib/test  //这个就是安装目录
libtt_la_LDFLAGS = -version-info @lt_major@:@lt_revision@:@lt_age@
libtt_la_LIBADD = @PTHREAD_LIBS@
libtt_la_SOURCES = \
                tt.c \
                video.c \
                video.h

当然,Makefile中的语法规则中还有很多宏定义,您可以在Makefile的官方网站找到说明。
下一篇就打算写写条件编译的Makefile写法。







 

posted on 2011-12-19 22:47 likun 阅读(1109) 评论(0)  编辑 收藏 引用 所属分类: C/C++Linux environment programmingDEBUG

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理