zoukankan      html  css  js  c++  java
  • gcc编译生成静态及动态链接库步骤

    gcc编译生成静态及动态链接库步骤

    这两天在看《Linux C程序设计大全》,吴岳编著,清华大学出版社。这本书是在一个培训机构看到的,在网上查了下该书的相关信息。从目录而言,该书涵盖了Linux下C程序设计的较多内容,包括C语言基础(主要讲解C语法结构)、C语言开发环境(主要介绍VIM使用、GCC使用、makefile编写、gdb使用)、Linux进程操作、Linux文件操作、Linux网络编程这几部分。阅读了该书几个小章节,总体而言,书的部分内容较充实,但是存在较多编辑错误,部分样例实际运行时与书中内容不符。

    这里使用该书P192-P199的例子,总结下gcc编译静态及动态链接库的方法及步骤。

    程序清单如下:

    test.c文件内容:
    int add(int a, int b)
    {
    return a + b;
    }

    int sub(int a, int b)
    {
    return a - b;
    }

    int mul(int a, int b)
    {
    return a * b;
    }

    int div(int a, int b)
    {
    return a / b;
    }


    test.h文件内容:
    #ifndef _TEST_H_

    #define _TEST_H_

    extern int add(int a, int b);
    extern int sub(int a, int b);
    extern int mul(int a, int b);
    extern int div(int a, int b);

    #endif


    main.c文件内容:
    #include <stdio.h>
    #include "test.h"

    int main ()
    {
    int a, b;
    printf("please input a and b ");
    scanf("%d%d", &a, &b);

    printf("The add : %d ", add(a, b));
    printf("The sub : %d ", sub(a, b));
    printf("The mul : %d ", mul(a, b));
    printf("The div : %d ", div(a, b));

    return 0;
    }


    1. 首先总结使用gcc生成静态库及使用静态库的方法:
    在此例中,test.c用于编译生成静态库libtest.a,test.h为libtest.a对应的头文件。

    step 1: 生成test.o目标文件,使用如下命令:
    [xgqin@xgqin-desktop so]$ ls
    main.c test.c test.h
    [xgqin@xgqin-desktop so]$ gcc -c test.c -o test.o
    [xgqin@xgqin-desktop so]$ ls
    main.c test.c test.h test.o
    在第一步中使用gcc -c test.c -o test.o首先生成test.o目标文件。

    step 2: 使用ar将test.o打包成libtest.a静态库,使用如下命令:
    [xgqin@xgqin-desktop so]$ ar rcs -o libtest.a test.o
    [xgqin@xgqin-desktop so]$ ls
    libtest.a main.c test.c test.h test.o
    step 3:生成libtest.a静态库后,可以使用ar t参数查看libtest.a文件中包含哪些文件:
    [xgqin@xgqin-desktop so]$ ar t libtest.a
    test.o
    [xgqin@xgqin-desktop so]$
    step 4: 编译main.c,并使用libtest.a静态库,链接时-l参数后不加空格指定所需链接的库,这里库名是libtest.a,但是只需要给出-ltest即可,ld会以libtest作为库的实际名字(例如-lm参数,实际表示链接libm库,也就是数学库):
    [xgqin@xgqin-desktop so]$ gcc -o app_static main.c -L. -ltest
    [xgqin@xgqin-desktop so]$ ls
    app_static libtest.a main.c test.c test.h test.o

    或使用如下方式编译main.c,并使用libtest.a静态库:
    [xgqin@xgqin-desktop so]$ gcc -o app_static main.c libtest.a
    [xgqin@xgqin-desktop so]$ ls
    app_static libtest.a main.c test.c test.h test.o
    step 5: 运行app_static:
    [xgqin@xgqin-desktop so]$ ./app_static
    please input a and b
    4 2
    The add : 6
    The sub : 2
    The mul : 8
    The div : 2
    [xgqin@xgqin-desktop so]$
    step 6: 使用readelf 查看app_static的符号表,观察sub, add, mul, div等函数是否处于app_static的.text段中。注意,section headers中指出 .text代码段的编号是13,而再symbol table ‘.symtab’中则显示add, div, mul, sub均处于13段中,也就是.text代码段中。因此libtest.a静态库经过链接后对应的函数代码已加入app_static程序代码段中,此为静态链接。

    [xgqin@xgqin-desktop so]$ readelf -a app_static
    ....
    Section Headers:
    [Nr] Name Type Address Offset
    Size EntSize Flags Link Info Align
    ....
    [13] .text PROGBITS 0000000000400520 00000520
    0000000000000274 0000000000000000 AX 0 0 16
    [14] .fini PROGBITS 0000000000400794 00000794
    0000000000000009 0000000000000000 AX 0 0 4
    [15] .rodata PROGBITS 00000000004007a0 000007a0
    0000000000000062 0000000000000000 A 0 0 8
    ....
    [29] .strtab STRTAB 0000000000000000 00001fb8
    000000000000027b 0000000000000000 0 0 1
    Symbol table '.symtab' contains 72 entries:
    Num: Value Size Type Bind Vis Ndx Name
    ....
    49: 00000000004006c4 20 FUNC GLOBAL DEFAULT 13 add
    ....
    53: 0000000000400701 19 FUNC GLOBAL DEFAULT 13 div
    ....
    64: 0000000000400610 179 FUNC GLOBAL DEFAULT 13 main
    65: 00000000004006ee 19 FUNC GLOBAL DEFAULT 13 mul
    ....
    70: 00000000004006d8 22 FUNC GLOBAL DEFAULT 13 sub
    ....
    注:《Linux C程序设计大全》中给出的三种链接静态库的方法在实际使用时均出现报错,如下所示:
    [xgqin@xgqin-desktop so]$ gcc main.c -llibtest.a -o app
    /usr/bin/ld: cannot find -llibtest.a
    collect2: error: ld returned 1 exit status
    [xgqin@xgqin-desktop so]$ gcc main.c -ltest.a -o app
    /usr/bin/ld: cannot find -ltest.a
    collect2: error: ld returned 1 exit status
    [xgqin@xgqin-desktop so]$ gcc main.c -ltest -o app
    /usr/bin/ld: cannot find -ltest
    collect2: error: ld returned 1 exit status
    [xgqin@xgqin-desktop so]$ gcc -L. main.c -o app
    /tmp/ccEpq6Fp.o: In function `main':
    main.c:(.text+0x37): undefined reference to `add'
    main.c:(.text+0x57): undefined reference to `sub'
    main.c:(.text+0x77): undefined reference to `mul'
    collect2: error: ld returned 1 exit status
    [xgqin@xgqin-desktop so]$ gcc main.c -static ./libtest.a -o app
    /usr/bin/ld: cannot find -lc
    collect2: error: ld returned 1 exit status
    [xgqin@xgqin-desktop so]$

    具体出错原因,个人推测应与ld相关。

    2. 再总结使用gcc生成动态库及使用动态库的方法:

    step 1: 生成test.o目标文件,使用如下命令。此处需要添加-fPIC参数,该参数用于生成位置无关代码已共生成动态库使用:
    [xgqin@xgqin-desktop so]$ gcc -c -o test.o -fPIC test.c
    [xgqin@xgqin-desktop so]$ ls
    app_static libtest.a main.c test.c test.h test.o
    [xgqin@xgqin-desktop so]$ file test.o
    test.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped

    step 2: 使用-shared参数生成动态库,使用如下命令:
    [xgqin@xgqin-desktop so]$ gcc -shared -o libmyshare.so test.o
    [xgqin@xgqin-desktop so]$ ls
    app_static libmyshare.so libtest.a main.c test.c test.h test.o
    [xgqin@xgqin-desktop so]$ file libmyshare.so
    libmyshare.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=0x4053caa2d2d48b9b026576a69929a4a44abedcb0, not stripped

    上述两个命令可以合在一块,如下所示:
    [xgqin@xgqin-desktop so]$ gcc -shared -fPIC -o libmyshare.so test.c
    [xgqin@xgqin-desktop so]$ file libmyshare.so
    libmyshare.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=0x4053caa2d2d48b9b026576a69929a4a44abedcb0, not stripped

    step 3: 编译main.c,使用libmyshare.so动态库:
    [xgqin@xgqin-desktop so]$ gcc -o app_share main.c -L. -lmyshare
    [xgqin@xgqin-desktop so]$ ls
    app_share app_static libmyshare.so libtest.a main.c test.c test.h test.o
    [xgqin@xgqin-desktop so]$ ldd app_share
    linux-vdso.so.1 => (0x00007fff3972c000)
    libmyshare.so => not found
    libc.so.6 => /lib64/libc.so.6 (0x0000003039600000)
    /lib64/ld-linux-x86-64.so.2 (0x0000003039200000)
    使用ldd命令查看app_share使用的动态库,发现提示libmyshare无法找到,如果直接执行app_share,则出现如下错误:
    [xgqin@xgqin-desktop so]$ ./app_share
    ./app_share: error while loading shared libraries: libmyshare.so: cannot open shared object file: No such file or directory
    查看相关资料后,提示与LD_LIBRARY_PATH相关,首先使用export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH将当前目录加入LD_LIBRARY_PATH变量中。
    再次运行ldd app_share,如下:
    [xgqin@xgqin-desktop so]$ gcc -o app_share main.c -L. -lmyshare
    [xgqin@xgqin-desktop so]$ ldd app_share
    linux-vdso.so.1 => (0x00007fff26b70000)
    libmyshare.so => not found
    libc.so.6 => /lib64/libc.so.6 (0x0000003039600000)
    /lib64/ld-linux-x86-64.so.2 (0x0000003039200000)
    [xgqin@xgqin-desktop so]$ export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
    [xgqin@xgqin-desktop so]$ echo $LD_LIBRARY_PATH
    .:
    [xgqin@xgqin-desktop so]$ ldd app_share
    linux-vdso.so.1 => (0x00007fff55dbe000)
    libmyshare.so => ./libmyshare.so (0x00007fb8c3b18000)
    libc.so.6 => /lib64/libc.so.6 (0x0000003039600000)
    /lib64/ld-linux-x86-64.so.2 (0x0000003039200000)
    [xgqin@xgqin-desktop so]$ ./app_share
    please input a and b
    4 2
    The add : 6
    The sub : 2
    The mul : 8
    The div : 2
    注:注意观察export前后的两次ldd执行时,libmyshare.so的指向情况。

    另一种编译main.c,并链接libmyshare.so的方式如下(该方式通过./libmyshare.so直接指定使用当前目录下的libmyshare.so文件:
    [xgqin@xgqin-desktop so]$ gcc -o app_share main.c ./libmyshare.so
    [xgqin@xgqin-desktop so]$ ldd app_share
    linux-vdso.so.1 => (0x00007fff066c3000)
    ./libmyshare.so (0x00007f945b6b0000)
    libc.so.6 => /lib64/libc.so.6 (0x0000003039600000)
    /lib64/ld-linux-x86-64.so.2 (0x0000003039200000)
    [xgqin@xgqin-desktop so]$ ./app_share
    please input a and b
    4 2
    The add : 6
    The sub : 2
    The mul : 8
    The div : 2
    [xgqin@xgqin-desktop so]$
    本文中使用到的readelf属于binutils工具集,感兴趣的读者可以访问google或者百度。



  • 相关阅读:
    HDU 1358 Period (KMP)
    POJ 1042 Gone Fishing
    Csharp,Javascript 获取显示器的大小的几种方式
    css text 自动换行的实现方法 Internet Explorer,Firefox,Opera,Safar
    Dynamic Fonts动态设置字体大小存入Cookie
    CSS Image Rollovers翻转效果Image Sprites图片精灵
    CSS three column layout
    css 自定义字体 Internet Explorer,Firefox,Opera,Safari
    颜色选择器 Color Picker,Internet Explorer,Firefox,Opera,Safar
    CSS TextShadow in Safari, Opera, Firefox and more
  • 原文地址:https://www.cnblogs.com/sun-frederick/p/4762871.html
Copyright © 2011-2022 走看看