• 动静态库【Linux】


    静态库的打包

    把我们提供的方法,给别人用:

    1、把源文件直接给别人
    2、把源代码打包成库=库+.h
    例如 ;有a.c b.c c.c d.c ,四个.c文件 ,
    将a.c 形成a.o ,b.c形成b.o c.c形成c.o d.c形成d.o文件,将这些文件打包
    在这里插入图片描述

    ar命令用于将目标文件打包为静态库

    -r(replace):若静态库文件当中的目标文件有更新,则用新的目标文件替换旧的目标文件。
    -c(create):建立静态库文件
    -t:列出静态库中的文件。
    -v(verbose):显示详细的信息

    在这里插入图片描述

    [cxq@iZ7xviiy0goapxtblgih6oZ test]$ tree .
    .
    ├── lib
    │   ├── include
    │   │   └── mymath.h
    │   └── mymathlib
    │       └── libmymath.a
    └── main.c
    
    3 directories, 3 files
    [cxq@iZ7xviiy0goapxtblgih6oZ test]$ ll
    total 8
    drwxrwxr-x 4 cxq cxq 4096 May 28 19:12 lib
    -rw-rw-r-- 1 cxq cxq   83 May 29 15:13 main.c
    [cxq@iZ7xviiy0goapxtblgih6oZ test]$ gcc main.c -I ./lib/include/ -L  ./lib/mymathlib/ -lmymath
    [cxq@iZ7xviiy0goapxtblgih6oZ test]$ ll
    total 20
    -rwxrwxr-x 1 cxq cxq 8536 May 29 16:26 a.out
    drwxrwxr-x 4 cxq cxq 4096 May 28 19:12 lib
    -rw-rw-r-- 1 cxq cxq   83 May 29 15:13 main.c
    [cxq@iZ7xviiy0goapxtblgih6oZ test]$ ./a.out
    1+1=2
    

    在这里插入图片描述

    -I 用来指明头文件在哪里
    -L用来指明库文件在哪里
    -l 表示需要链接的库的名称

    **往后使用第三方库的时候,必定要是用gcc -l **

    在这里插入图片描述
    如果系统中只提供静态链接,gcc则只能对该库进行静态链接
    如果系统中需要链接多个库,则gcc可以链接多个厍

    将头文件和库文件拷贝到系统的默认目录下

    [cxq@iZ7xviiy0goapxtblgih6oZ test]$ tree .
    .
    ├── a.out
    ├── lib
    │   ├── include
    │   │   └── mymath.h
    │   └── mymathlib
    │       └── libmymath.a
    └── main.c
    
    3 directories, 4 files
    [cxq@iZ7xviiy0goapxtblgih6oZ test]$ sudo cp lib/include/mymath.h /usr/include/
    [sudo] password for cxq: 
    [cxq@iZ7xviiy0goapxtblgih6oZ test]$ ls /usr/include/mymath.h
    /usr/include/mymath.h
    [cxq@iZ7xviiy0goapxtblgih6oZ test]$ sudo cp lib/mymathlib/libmymath.a  /lib64/
    [cxq@iZ7xviiy0goapxtblgih6oZ test]$ ls /lib64/libmymath.a
    /lib64/libmymath.a
    [cxq@iZ7xviiy0goapxtblgih6oZ test]$ ll
    total 20
    -rwxrwxr-x 1 cxq cxq 8536 May 29 16:26 a.out
    drwxrwxr-x 4 cxq cxq 4096 May 28 19:12 lib
    -rw-rw-r-- 1 cxq cxq   83 May 29 15:13 main.c
    [cxq@iZ7xviiy0goapxtblgih6oZ test]$ gcc main.c -lmymath
    [cxq@iZ7xviiy0goapxtblgih6oZ test]$ ./a.out
    1+1=2
    

    在这里插入图片描述
    库的安装就是将头文件和库文件拷贝到系统的默认目录下

    建立软链接

    [cxq@iZ7xviiy0goapxtblgih6oZ test]$ tree ../
    ../
    ├── libmymath.a
    ├── Makefile
    ├── mymath.c
    ├── mymath.h
    ├── mymath.o
    └── test
        ├── a.out
        ├── lib
        │   ├── include
        │   │   └── mymath.h
        │   └── mymathlib
        │       └── libmymath.a
        └── main.c
    
    4 directories, 9 files
    [cxq@iZ7xviiy0goapxtblgih6oZ test]$  sudo ln -s /home/cxq/lesson23/test/lib/include /usr/include/myinc
    [cxq@iZ7xviiy0goapxtblgih6oZ test]$ ls /usr/include/myinc
    mymath.h[cxq@iZ7xviiy0goapxtblgih6oZ test]$ ls -l  /usr/include/myinc
    lrwxrwxrwx 1 root root 35 May 30 16:36 /usr/include/myinc -> /home/cxq/lesson23/test/lib/include
    [cxq@iZ7xviiy0goapxtblgih6oZ test]$ sudo ln -s  /home/cxq/lesson23/test/lib/mymathlib/libmymath.a  /lib64/libmymath.a
    [cxq@iZ7xviiy0goapxtblgih6oZ test]$ ls  /lib64/libmymath.a
    /lib64/libmymath.a
    [cxq@iZ7xviiy0goapxtblgih6oZ test]$ ll
    total 8
    drwxrwxr-x 4 cxq cxq 4096 May 28 19:12 lib
    -rw-rw-r-- 1 cxq cxq   90 May 30 21:49 main.c
    [cxq@iZ7xviiy0goapxtblgih6oZ test]$ gcc main.c -lmymath
    [cxq@iZ7xviiy0goapxtblgih6oZ test]$ ll
    total 20
    -rwxrwxr-x 1 cxq cxq 8536 Jun  1 09:12 a.out
    drwxrwxr-x 4 cxq cxq 4096 May 28 19:12 lib
    -rw-rw-r-- 1 cxq cxq   90 May 30 21:49 main.c
    [cxq@iZ7xviiy0goapxtblgih6oZ test]$ ./a.out
    1+1=2
    
    

    在这里插入图片描述

    动态库的打包

    将多个.c文件形成多个.o文件,然后将形成的这些.o文件打包,形成动态库
    无论是动态库还是静态库,都要先形成.o文件

    在这里插入图片描述

    将多个.c文件形成多个.o文件

    [cxq@iZ7xviiy0goapxtblgih6oZ lesson23]$ gcc  -fPIC -c myprint.c
    [cxq@iZ7xviiy0goapxtblgih6oZ lesson23]$ gcc  -fPIC -c mylog.c
    

    -fPIC(position independent code):产生位置无关码

    1、-fPIC作用于编译阶段,告诉编译器产生与位置无关的代码,此时产生的代码中没有绝对地址,全部都使用相对地址,从而代码可以被加载器加载到内存的任意位置都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的。

    2、如果不加-fPIC选项,则加载.so文件的代码段时,代码段引用的数据对象需要重定位,重定位会修改代码段的内容,这就造成每个使用这个.so文件代码段的进程在内核里都会生成这个.so文件代码段的拷贝,并且每个拷贝都不一样,取决于这个.so文件代码段和数据段内存映射的位置。

    3、不加-fPIC编译出来的.so是要在加载时根据加载到的位置再次重定位的,因为它里面的代码BBS位置无关代码。如果该.so文件被多个应用程序共同使用,那么它们必须每个程序维护一份.so的代码副本(因为.so被每个程序加载的位置都不同,显然这些重定位后的代码也不同,当然不能共享)。

    4、我们总是用-fPIC来生成.so,但从来不用-fPIC来生成.a。但是.so一样可以不用-fPIC选项进行编译,只是这样的.so必须要在加载到用户程序的地址空间时重定向所有表目

    在这里插入图片描述

    打包

    [cxq@iZ7xviiy0goapxtblgih6oZ lesson23]$ gcc -shared -o libmymethod.so *.o
    

    在这里插入图片描述

    将.c文件形成.o文件和打包融合到Makefile里面

    在这里插入图片描述

    [cxq@iZ7xviiy0goapxtblgih6oZ lesson23]$ make ; make output
    gcc -fPIC -c  mylog.c
    gcc -fPIC -c myprint.c
    gcc -shared  -o libmymethod.so mylog.o myprint.o
    gcc -c mymath.c
    ar -rc libmymath.a mymath.o  
    mkdir -p mylib/include
    mkdir -p mylib/lib
    cp *.h mylib/include
    cp *.a mylib/lib
    cp *.so mylib/lib
    [cxq@iZ7xviiy0goapxtblgih6oZ lesson23]$ ll
    total 60
    -rw-rw-r-- 1 cxq cxq 1880 Jun  1 16:26 libmymath.a
    -rwxrwxr-x 1 cxq cxq 8144 Jun  1 16:26 libmymethod.so
    -rw-rw-r-- 1 cxq cxq  460 Jun  1 16:25 Makefile
    drwxrwxr-x 4 cxq cxq 4096 Jun  1 16:26 mylib
    -rw-rw-r-- 1 cxq cxq   85 Jun  1 14:44 mylog.c
    -rw-rw-r-- 1 cxq cxq   62 Jun  1 14:53 mylog.h
    -rw-rw-r-- 1 cxq cxq 1568 Jun  1 16:26 mylog.o
    -rw-rw-r-- 1 cxq cxq  265 May 28 18:20 mymath.c
    -rw-rw-r-- 1 cxq cxq  159 May 28 18:19 mymath.h
    -rw-rw-r-- 1 cxq cxq 1704 Jun  1 16:26 mymath.o
    -rw-rw-r-- 1 cxq cxq  176 Jun  1 14:43 myprint.c
    -rw-rw-r-- 1 cxq cxq   55 Jun  1 14:43 myprint.h
    -rw-rw-r-- 1 cxq cxq 1728 Jun  1 16:26 myprint.o
    drwxrwxr-x 3 cxq cxq 4096 Jun  1 09:12 test
    

    使用静态库:
    在这里插入图片描述

    使用动态库:

    [cxq@iZ7xviiy0goapxtblgih6oZ test]$ gcc main.c -lmymethod  -I  mylib/include/   -L  mylib/lib
    [cxq@iZ7xviiy0goapxtblgih6oZ test]$ ll
    total 20
    -rwxrwxr-x 1 cxq cxq 8384 Jun  2 16:52 a.out
    -rw-rw-r-- 1 cxq cxq  168 Jun  2 15:43 main.c
    drwxrwxr-x 4 cxq cxq 4096 Jun  2 16:20 mylib
    [cxq@iZ7xviiy0goapxtblgih6oZ test]$ ./a.out
    hello new world!
    hello new world!
    hello new world!
    hello new world!
    Warning: hello log function
    [cxq@iZ7xviiy0goapxtblgih6oZ test]$ tree .
    .
    ├── a.out
    ├── main.c
    └── mylib
        ├── include
        │?? ├── mylog.h
        │?? ├── mymath.h
        │?? └── myprint.h
        └── lib
            ├── libmymath.a
            └── libmymethod.so
    
    3 directories, 7 files
    

    在这里插入图片描述

    动态库和静态库一起使用:

    [cxq@iZ7xviiy0goapxtblgih6oZ test]$ gcc  main.c  -lmymath -lmymethod -I mylib/include/   -L mylib/lib
    [cxq@iZ7xviiy0goapxtblgih6oZ test]$ ll
    total 20
    -rwxrwxr-x 1 cxq cxq 8608 Jun  2 18:21 a.out
    -rw-rw-r-- 1 cxq cxq  164 Jun  2 18:20 main.c
    drwxrwxr-x 4 cxq cxq 4096 Jun  2 16:20 mylib
    [cxq@iZ7xviiy0goapxtblgih6oZ test]$ ./a.out
    1+1=2
    hello new world!
    hello new world!
    hello new world!
    hello new world!
    Warning: hello log function
    
    

    在这里插入图片描述

    在这里插入图片描述
    出现上述现象原因:
    gcc main.c -lmymethod -I mylib/include/ -L mylib/lib
    动态库的路径已经告诉编译器路径了,但是没有告诉系统(加载器),
    对于动态库,动态库是一个独立的文件,形成的可执行程序文件和动态库文件,这两者是两个不同的文件,

    解决加载找不到动态库的四种方案(第一种最常用):
    1.拷贝到系统默认的库路径/lib64(常用) 或者 /usr/lib64/ (不常用)
    2.在系统默认的库路径/lib64(常用)或者 /usr/lib64/(不常用)下建立软连接

    [cxq@iZ7xviiy0goapxtblgih6oZ test]$ tree .
    .
    ├── a.out
    ├── main.c
    └── mylib
        ├── include
        │   ├── mylog.h
        │   ├── mymath.h
        │   └── myprint.h
        └── lib
            ├── libmymath.a
            └── libmymethod.so
    
    3 directories, 7 files
    [cxq@iZ7xviiy0goapxtblgih6oZ test]$ pwd
    /home/cxq/lesson24/test
    [cxq@iZ7xviiy0goapxtblgih6oZ test]$ sudo ln -s /home/cxq/lesson24/test/mylib/lib/libmymethod.so  /lib64/libmymethod.so
    [sudo] password for cxq: 
    [cxq@iZ7xviiy0goapxtblgih6oZ test]$ ls /lib64/libmymethod.so
    /lib64/libmymethod.so
    
    

    在这里插入图片描述

    3.将自己的库所在的路径,添加到系统的环境变量LD_LIBRARY_PATH

    [cxq@iZ7xviiy0goapxtblgih6oZ test]$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/cxq/lesson24/test/mylib/lib 
    

    在这里插入图片描述
    但是如果关闭xshell,刚刚添加的路径就没了
    如果需要长期有效:

    [cxq@iZ7xviiy0goapxtblgih6oZ test]$ vim ~/.bash_profile
    

    在这里插入图片描述

    4./etc/ld.so.conf.d建立自己的动态库路径的配置文件,然后重新ldconfig即可

    [root@iZ7xviiy0goapxtblgih6oZ test]# cd /etc/ld.so.conf.d
    [root@iZ7xviiy0goapxtblgih6oZ ld.so.conf.d]# ll
    total 16
    -rw-r--r--  1 root root 26 Oct 16  2023 bind-export-x86_64.conf
    -r--r--r--  1 root root 63 Jan 26 00:21 kernel-3.10.0-1160.108.1.el7.x86_64.conf
    -r--r--r--. 1 root root 63 Oct 20  2020 kernel-3.10.0-1160.el7.x86_64.conf
    -rw-r--r--. 1 root root 17 Oct  2  2020 mariadb-x86_64.conf
    [root@iZ7xviiy0goapxtblgih6oZ ld.so.conf.d]# touch cxq.conf
    
    

    在这里插入图片描述
    动态库在进程运行的时候,是要被加载的(静态库没有)
    常见的动态库被所有的可执行程序(动态链接的),都要使用,所以动态库也叫做共享库
    所以,动态库在系统中加载之后,会被所有进程共享

  • 相关阅读:
    基于C#的学生综合教务管理系统
    Docker学习笔记
    Mac下更新python
    2022/6/27 Quartz(定时任务)讲解+入门案例
    ubuntu按下del却出现空格(命令行下键盘错乱)
    Day02 Git命令【添加暂存区】
    自然语言处理(NLP)-spacy简介以及安装指南(语言库zh_core_web_sm)
    Chrome 扩展是什么?我们如何建造它?
    Java版本spring cloud + spring boot企业电子招投标系统源代码
    你写过的最蠢的代码是?——全栈开发篇
  • 原文地址:https://blog.csdn.net/qq_73478334/article/details/139275068