使用libtool

摘自 libtool官方文档


Introduction

在本文中,我们的目标是构造一个名为libhello的库。这里,libhello可以是一个动态库,也可以是一个静态库。




Using libtools

首先下载一个libtool的安装包,解压后找到里面的demo文件夹,里面有文件hello.c和foo.c,我们将从这两个文件构造libhello库。


由于foo.c文件调用了cos函数(cos函数定义在一个单独的数学库中,而不是标准的C库),因此,我们在将foo.lo链接进一个可执行文件或者库的时候,需要加上-lm选项。同理,如果使用了不在C标准库中定义的函数,那么在链接时就需要使用-lname选项



Create object files

首先,创建一个空文件夹codes,然后将文件main.c、hello.c、foo.c和foo.h都复制到codes下。此时,执行命令ls -al可以看到以下输出:

        -rw-r--r-- 1 root root 1192 Sep 11 09:30   foo.c
        -rw-r--r-- 1 root root 3316 Sep 11 09:30   foo.h
        -rw-r--r-- 1 root root 1127 Sep 11 09:33   hello.c
        -rw-r--r-- 1 root root 1277 Sep 11 09:30   main.c


然后通过以下命令来创建一些目标文件:

        gcc -g -O -c main.c

        gcc -g -O -c hello.c

        gcc -g -O -c foo.c

这里,-g表示生成调试信息,-c表示只编译而不链接

这时,通过ls -al 可以看到生成了下列目标文件:main.o,foo.o,以及hello.o


共享库(shared libraries)只能从位置无关代码(position-independent code, PIC)创建,所以在编译时必须将一个特别的标志位告诉编译器让其创建PIC而不是标准的位置有关代码。


libtool隐藏了传递PIC标志位的细节,并分别创建了各种库文件(PIC库文件在.libs目录下,静态库文件则在当前目录下)。在不支持共享库的系统上,PIC库文件不会被创建;而在一些视所有文件为PIC的系统上(如AIX),静态库文件不会被创建。


下面使用libtool为foo.c和hello.c创建库文件:

        libtool --mode=compile gcc -g -O -c foo.c

        libtool --mode=compile gcc -g -O -c hello.c

这时,可以看到,在当前目录下新生成了4个文件(foo.o,foo.lo,hello.o,hello.lo)和1个隐藏目录(.libs目录,里面有2个文件foo.o和hello.o)。libtool利用.lo文件来决定将哪一个目标文件链接进共享库。hello.lo文件内容如下:

        # hello.lo - a libtool object file
        # Generated by ltmain.sh (GNU libtool) 2.2.6b
        #
        # Please DO NOT delete this file!
        # It is necessary for linking the library.

        # Name of the PIC object.
        pic_object='.libs/hello.o'

        # Name of the non-PIC object
        non_pic_object='hello.o'

       

在支持共享库的系统中,libtool会通过自动加入一个PIC选项的方式在编译时创建一个PIC目标文件

例如,我们输入命令 libtool --mode=compile gcc -g -O -c hello.c时,屏幕上会输出

        libtool: compile:  gcc -g -O -c hello.c  -fPIC -DPIC -o .libs/hello.o
        libtool: compile:  gcc -g -O -c hello.c -o hello.o >/dev/null 2>&1

生成的PIC目标文件(hello.o和foo.o)就保存在.libs隐藏目录中。



Linking libraries

如果不使用libtool,我们就需要用ar命令来创建静态库:

        ar aru libhello.a hello.o foo.o


许多系统还会要求你对生成的libhello.a运行ranlib命令:

        ranlib libhello.a


在此声明,libtool的控制文件(以.la结尾)与标准库文件(.a结尾)是不同的。使用libtool来创建libhello.la文件的命令如下:

        lintool --mode=linke gcc -g -O -o libhello.la foo.o hello.o

执行后,屏幕输出如下:

        [root@master codes]# libtool --mode=link gcc -g -O -o libhello.la foo.o hello.o

        *** Warning: Linking the shared library libhello.la against the non-libtool
        *** objects  foo.o hello.o is not portable!

        libtool: link: ar cru .libs/libhello.a
        libtool: link: ranlib .libs/libhello.a
        libtool: link: ( cd ".libs" && rm -f "libhello.la" && ln -s "../libhello.la" "libhello.la" )


这里报告了一个错误:试图从标准目标文件(.o文件)而不是从.la对象文件创建库文件。这对于静态库不重要,但是对于共享库的意义却非同寻常


所以,我们需要重新链接。由于foo.c使用了数学库里的cos函数,因此在链接时需要加上-lm选项。另外,我们还需要指定他们最终将被安装的路径(本文中是/usr/local/lib):

        libtool --mode=link gcc -g -O -o libhello.la foo.lo hello.lo -rpath /usr/local//lib -lm

执行后,屏幕输出如下:

        [root@master codes]# libtool --mode=link gcc -g -O -o libhello.la foo.lo hello.lo -rpath /usr/local/lib -lm
        libtool: link: rm -fr  .libs/libhello.a
        libtool: link: gcc -shared  .libs/foo.o .libs/hello.o   -lm    -Wl,-soname -Wl,libhello.so.0 -o .libs/libhello.so.0.0.0
        libtool: link: (cd ".libs" && rm -f "libhello.so.0" && ln -s "libhello.so.0.0.0" "libhello.so.0")
        libtool: link: (cd ".libs" && rm -f "libhello.so" && ln -s "libhello.so.0.0.0" "libhello.so")
        libtool: link: ar cru .libs/libhello.a  foo.o hello.o
        libtool: link: ranlib .libs/libhello.a
        libtool: link: ( cd ".libs" && rm -f "libhello.la" && ln -s "../libhello.la" "libhello.la" )


可以看到,libtool通过ld命令同时生成了共享库和静态库。此时,当前目录下新生成了libhello.la文件,同时,在.libs目录下新生成了以下文件:

        -rw-r--r--     1 root  root  12606  Sep 11 13:51  libhello.a
        lrwxrwxrwx 1 root  root  14         Sep 11 13:51  libhello.la -> ../libhello.la
        -rw-r--r--     1 root  root   931      Sep 11 13:51  libhello.lai
        lrwxrwxrwx 1 root  root   17        Sep 11 13:51  libhello.so -> libhello.so.0.0.0
        lrwxrwxrwx 1 root  root   17        Sep 11 13:51  libhello.so.0 -> libhello.so.0.0.0
        -rwxr-xr-x    1 root  root   10419 Sep 11 13:51  libhello.so.0.0.0


我们打开libhello.la文件,看一看libtool在里面写入了什么内容:

# The name that we can dlopen(3).
dlname='libhello.so.0'

# Names of this library.
library_names='libhello.so.0.0.0 libhello.so.0 libhello.so'

# The name of the static archive.
old_library='libhello.a'

# Linker flags that can not go in dependency_libs.
inherited_linker_flags=''

# Libraries that this one depends upon.
dependency_libs=' -lm'

# Names of additional weak libraries provided by this library
weak_library_names=''

# Version information for libhello.
current=0
age=0
revision=0

# Is this an already installed library?
installed=no

# Should we warn about portability when linking against -modules?
shouldnotlink=no

# Files to dlopen/dlpreopen
dlopen=''
dlpreopen=''

# Directory that this library needs to be installed in:
libdir='/usr/local/lib'

可以看到,libhello.la中保存了一下信息:保存库文件的路径(即 "-rpath" 参数)以及对数学库的依赖(即 "-lm" 参数)。




Lining executables

如果此时你选择安装库(即将库放在某个路径下),那么你就不需要用libtool来进行链接:只需要使用-L和-l来执行库的路径即可。

















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值