静态库的打包
把我们提供的方法,给别人用:
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
动态库在进程运行的时候,是要被加载的(静态库没有)
常见的动态库被所有的可执行程序(动态链接的),都要使用,所以动态库也叫做共享库
所以,动态库在系统中加载之后,会被所有进程共享