如何电脑上共享代码
如果你在同一台计算机上做编程工作,你想在多个程序中使用相同的代码,但又不想每个程序都保留一份相同的代码。那么最好的做法就是共享这部分代码,我们可以在程序之间共享两类代码:.h头文件和.o目标文件。
那么应该怎么共享呢?
共享.h头文件
有两种方式:
1.把.h头文件保存在标准目录中,在类Unix系统中,标准目录就是/usr/local/include
只要头文件在标准目录中,就可以用尖括号包含它们,如共享.encrypt.h文件:
~$mv encrypt.h /usr/local/include
//在代码中包含头文件
#include <encrypt.h>
- 1
- 2
- 3
2.把头文件放在非标准目录中,在使用时,就要用完整的路径名,不能使用尖括号,如:
~/Desktop/Mc$ mkdir ~/my_head_file
~/Desktop/Mc$ mv encrypt.h ~/my_head_file //在代码中包含头文件
#include "/home/wong/my_head_file/encrypt.h"
- 1
- 2
- 3
- 4
- 5
如果你没有使用完整路径名引用头文件,就要告诉编译器去哪里找头文件:
如果此时头文件中/home/wong/my_head_file中,如test.c文件中是如此#include "encrypt.h"包含了此头文件,那么就要这样编译:
$ gcc -I/home/wong/my_head_file encrypt.c checksum.c test.c -o test
- 1
注:-I就是告诉编译器去哪里找头文件的
共享.o目标文件
1.可以把.o目录文件放在一个目录下,所以编译时,只在目标文件前加上完整路径即可:
~/Desktop/Mc$ mkdir ~/my_object_file
~/Desktop/Mc$ mv encrypt.o checksum.o ~/my_object_file
~/Desktop/Mc$ gcc -I/home/wong/my_head_file test.c /home/wong/my_object_file/encrypt.o /home/wong/my_object_file/checksum.o -o test
- 1
- 2
- 3
但是上面这种共享会让人很累,如果一两个还好,多了的话,就那是受罪,因此提供另外一种方法,就是将目标文件存档,即将一批目标文件打包在一起,然后就可以一次告诉编译器一批目标文件了。
存档文件的后缀名是.a。
存档文件的标准命名方式是libXXX.a的形式。
存档是静态库,编译时会把代码放到你的程序中,文章后面会价绍动态库。
用ar命令创建存档:
~/Desktop/Mc$ ar -rcs libencrypchecksum.a encrypt.o checksum.o
- 1
介绍一下参数:
r:表示如果.a文件存在就更新它。
c:创建存在时不显示反馈信息
s: 告诉ar要在.a文件开头建立索引
.a存档文件可以放哪里呢?
1.可以放在标准目录/usr/local/lib,编译就无需要告诉编译器要去哪里找存档文件:
~/Desktop/Mc$ gcc test.c -lencrypchecksum -o test
- 1
2.还可以放在其他目录中,编译就需要告诉编译器要去哪里找存档文件。
~/Desktop/Mc$ mkdir ~/my_lib
~/Desktop/Mc$ mv libencrypchecksum.a ~/my_lib
~/Desktop/Mc$ gcc -I/home/wong/my_head_file test.c -L/home/wong/my_lib -lencrypchecksum -o test
- 1
- 2
- 3
-L参数就是告诉编译器去哪里找存档文件的。
-l参数后就是跟存档名,注意存档名是去掉了lib和.a的部分。
如果想从存档文件中提取目标文件,也是可以的,如我们提取encrypt.o文件,方法如下:
~/my_lib$ ar -x libencrypchecksum.a encrypt.o
~/my_lib$ ls
encrypt.o libencrypchecksum.a
- 1
- 2
- 3
这样encrypt.o文件就被提取出来了。
上面就是共享.h头文件和.o目标文件的方法。
上面的编译都是静态编译,或者说是静态链接,一旦链接了就不能更改了,也就是说,这些目录文件的代码被包含进程序,如果要修改这些目标文件,那程序只能重新编译了。
但是如果这些目标文件做成动态库,那问题很好办了。动态库与存档很像,不同的地方就是在动态库中,目标文件会链接成一段目标代码。动态库有上些额外信息,操作系统需要用这些信息把库连接到程序。
因为库是动态的,所以使用动态库编译时,编译器不会在可执行文件中包含库代码,即目标文件的代码不会被包含进程序,而是会在可执行文件中插入一段用来查找库的“占位符”代码,并在运行时链接库。
动态库在不同平台有不同叫法:
在Linux和Unix上叫共享目标文件,后缀名是.so
在Mac平台上,叫动态库,后缀名是.dylib
在Windows平台上,叫动态链接库,后缀名是.dll
我们开始创建动态库吧。
1.首先创建目标文件:
~/Desktop/Mc$ gcc -I/home/wong/my_head_file -fPIC -c encrypt.c
~/Desktop/Mc$ gcc -I/home/wong/my_head_file -fPIC -c checksum.c
- 1
- 2
-c:表示不要链接代码
-fPIC:告诉gcc编译器创建位置无关代码
位置无关的代码就是无论计算机把它加载到存储器的哪个位置都可以运行的代码。例如,有个动态库,它要加载800个字节外的某个全局变量的值,如果操作系统把动态库载到其他地方,就会出错,只有创建了位置无关的动态库才能解决此问题。
有的操作系统和处理器要用位置无关代码创建库,这样它们才能在运行时决定把代码加载到存储器的哪个位置。事实上大多数操作系统都不需要加这个选择。
2.创建动态库
我们把ecnrypt.o和checksum.o编进动态库里去
~/Desktop/Mc$ gcc -shared encrypt.o checksum.o -o libencryptchecksum.so
- 1
-shared选项就是告诉gcc我们想把.o目标文件转化为动态库。
linux和Unix平台上动态库的标准命名方式是:libXXX.so
注意:上面创建了一个叫libencryptchecksum.so的库,那么libencryptchecksum.so文件就会记录它的库名叫encryptchecksum,就是说一旦用了某个名字编译了动态库,就不能再修改文件名了。若想重命名库,就必须用新的名字重新编译一次。
3.用动态库编译程序
~/Desktop/Mc$ gcc -I/home/wong/my_head_file -c test.c -o test.o
~/Desktop/Mc$ gcc test.o -L/home/wong/my_lib -lencryptchecksum -o test
~/Desktop/Mc$ ./test
./test: error while loading shared libraries: libencryptchecksum.so: cannot open shared object file: No such file or directory
- 1
- 2
- 3
- 4
成功编译了,但是运行的时候出错了!!!
原因:在Linux和大部分Unix中,编译器只会记录libencryptchecksum.so库的文件名,而不会记录路径名。
如果不是把动态库保存到标准库/usr/lib中,程序就会找不到它,为了解决这个问题,Linux会检查保存在LD_LIBRARY_PATH变量中的附加目录,只要把库目录添加到这LD_LIBRARY_PATH中,并export它,程序就能找到libencryptchecksum.so库了。
~/Desktop/Mc$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:~/my_lib
~/Desktop/Mc$ ./test
!!!!!
- 1
- 2
- 3
这样就可以了,另外提醒一点,在命令行export只是临时的,一关掉命令行(终端)就没有了。要永久的话,可以在/etc/profile或~/.profile或 /home/wong/.bashrc等配置文件中配置。
静态链接和动态链接哪个好呢,使用静态链接可以得到一个小而快的可执行文件,可以很方便地从一台机器拷贝到另一台机器,而而动态链接允许在运行时配置程序。一般驱动都会做成动态库。
文章来源: blog.csdn.net,作者:WongKyunban,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/weixin_40763897/article/details/87476181
- 点赞
- 收藏
- 关注作者
评论(0)