软件技术网站怎么做,招标网站平台,网站开发学习步骤,青岛城市建设集团网站目录
写在前面的话
如何编写静态库库
编写静态库
ar命令
Makefile自动化形成静态库
如何使用编写的静态库
1.拷贝到系统路径中
2.指定路径搜索
如何编写动态库
编写动态库
完善Makefile
如何使用编写的动态库
指定路径搜索(不可行及原因)
环境变量LD_LIBRARY_PAT…目录
写在前面的话
如何编写静态库库
编写静态库
ar命令
Makefile自动化形成静态库
如何使用编写的静态库
1.拷贝到系统路径中
2.指定路径搜索
如何编写动态库
编写动态库
完善Makefile
如何使用编写的动态库
指定路径搜索(不可行及原因)
环境变量LD_LIBRARY_PATH
修改配置文件 写在前面的话 本文章主要讲解了动静态库的编写以及使用。在了解静态链接和动态链接的基础上观看本文的效果会更好。 欢迎阅读我之前写的动静态链接里面有关于动态和静态链接的详细介绍而且也有对动静态库的一些基本认识欢迎阅读哦.
如何编写静态库 这里我们将编写两个类型的库动态库(.so) 和 静态库(.a).
编写静态库 静态库.a程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库. 需要说明库里不能包含main函数因为是要别人用的。写main函数的话就会和别人的main函数冲突了. 我现在分别创建了4个文件mymath.h mymath.c myprint.h myprint.c.
分别写入以下内容 mymath.h #pragma once
#includestdio.h extern int addToTarget(int start, int end);//声明函数 mymath.c #include mymath.h # //这段函数的作用是计算start-end之间的和int addToTarget(int start, int end) { int sum 0; int i start; for(i; i end; i){ sum i; } return sum; } myprint.h #pragma once #includestdio.h
#includetime.h extern void Print(const char* str); myprint.c #include myprint.h //这段函数功能是输出传入的字符串后面加上时间戳
void Print(const char* str)
{printf(%s[%d]\n,str,(int)(time(NULL)));
} 然后我们编写一个main.c文件来调用这些函数.
#include myprint.h
#include mymath.h int main()
{ Print(hello,world); int res addToTarget(1,100); printf(res: %d\n,res); return 0;
} 指令编译所有.c文件目标生成my.exe可执行文件
gcc main.c mymath.c myprint.c -o my.exe 然后我们执行my.exe文件得到了我们预期的结果 这只是我们的正常使用毕竟源代码.c文件就在我们手上。 当我们把.h文件和 .c文件编译成的.o文件给别人别人可以用吗 答案是可以的我们首先把两个.c文件编译成.o文件
gcc -o myprint.o -c myprint.c
gcc -o mymath.o -c mymath.c然后我们换到另一个文件中把两个.o和两个.h文件复制到这个文件中然后将main.c也编译成main.o文件此时我们将这三个.o文件一起编译形成可执行程序。
gcc main.o mymath.o myprint.o -o my.exe我们发现照样可以成功运行 但问题是我们这里有太多的.o文件发给别人也不方便而且容易丢失编译的时候还得都写上这也未必太麻烦了。
所以此时我们需要把这些.o文件打包这个打包的过程就是形成静态库的过程.
ar命令 把这些.o文件打包需要用到ar命令命令格式如下 ar -[选项] lib库文件名.a 所有.o文件 选项这里只说r(replace替换)c(create创建)就可以了就足以让我们创建静态库了. 其中需要注意的是要形成的静态库的名字 前缀必须是lib后缀必须是.a中间可以随便起名字. 比如我想把所有的.o文件打包成名字叫hello的静态库指令如下
ar -rc libhello.a main.o myprint.o mymath.o这样就形成了.
Makefile自动化形成静态库 有了以上的认知我们便对一个文件形成静态库的过程有了大概的了解 .c文件 --- .o文件 --- 打包形成静态库
既然是这么一套固定的流程那么我们完全可以用Makefile来完成这些工作。需要注意的是搞清各个文件的依赖关系然后再进行编写。所以最后的Makefile编写如下
libhello.a: mymath.o myprint.o ar -rc libhello.a mymath.o myprint.o
mymath.o : mymath.c gcc -o mymath.o -c mymath.c
myprint.o: myprint.c gcc -o myprint.o -c myprint.c .PHONY:clean
clean: rm -rf *.o libhello.a 这样我们不需要再手动编译了直接使用make就好了. 但这样只是将.o文件打包了还有.h文件就是通常#include的那些一般都是.h文件
.h声明然后从.o打包形成的库里面找
所以我们还需要做一件工作将.h和.o文件规整到一起.在Makefile加入以内容
.PHONY:hello
hello: mkdir -p hello/lib mkdir -p hello/include cp -rf *.h hello/include cp -rf *.a hello/lib 即创建了三个目录hello,lib和include把当前所有的.h文件放到include文件夹中所有.a库文件放到lib文件夹中。 这里首先把资源全部清理一下然后make编译形成.o文件再make hello 形成hello目录里面包含了两个目录include 和 lib 分别保存.h文件和库文件. 如何使用编写的静态库
1.拷贝到系统路径中 头文件gcc系统默认搜索路径是/usr/include 库文件gcc系统默认搜索路径是/lib64 或者 /usr/lib64
sudo cp hello/include/*.h /usr/include/ //拷贝头文件
sudo cp hello/lib/*.a /lib64 //拷贝库文件
拷贝完成后我们再次编译main.c 发现还是不行这是由于我们平常使用的是系统自带的库而我们编写的是第三方库所以我们编译时需要指定链接哪一个库.
gcc main.c -lhello 注意-l后面直接加库的名字不加前缀lib和后缀.a. 此时我们再编译便运行成功了. 这种把自己的库拷贝到系统路径下的行为就叫做库的安装.
但是一般不建议采用这种办法。会污染别人已经写好的库。
2.指定路径搜索
我们可以直接在编译的时候加上头文件和库文件的路径.
gcc main.c -I ./hello/include/ -L ./hello/lib/ -lhello选项-I(i的大写)表示头文件的搜索路径 -L表示库文件的搜索路径 -l(小写的L)表示在特定路径下要使用哪一个库. 如何编写动态库 动态库.so程序在运行的时候才去链接动态库的代码多个程序共享使用库的代码。
编写动态库 同样地我么也需要先将.c文件编译成.o文件但此时需要加上选项 -fPIC.
gcc -fPIC -c myprint.c -o myprint.o
gcc -fPIC -c mymath.c -o mymath.o选项-fPIC是指生成位置独立代码Position Independent CodePIC。它通常用于创建可在不同内存地址空间加载的共享库动态链接库。 具体来说-fPIC选项的作用是告诉编译器生成与位置无关的代码这些代码可以在内存中的任何位置加载和执行与共享库的加载地址无关。这是通过使用相对偏移而不是绝对地址来访问全局变量和函数等的。 看不懂没有关系我们后面会继续细说的.
然后我们需要将这些.o文件它打包成动态库.它没有单独的命令使用gcc进行打包但是需要加上 -shared的选项如下
gcc -shared myprint.o mymath.o -o libhello.so这样我们就完成了动态库的打包和编写. 由于流程是固定的所以我们依然可以使用Makefile来完成。
完善Makefile 首先我们需要先将.c编译诚.o文件并打包成动态库 然后需要将生成的动态库也放到我们之前创建的lib目录中。 完善后的效果如下(框起来的是新增的内容)
.PHONY:all
all:libhello.so libhello.a libhello.so:mymath_d.o myprint_d.o gcc -shared mymath_d.o myprint_d.o -o libhello.so
mymath_d.o:mymath.c gcc -c -fPIC mymath.c -o mymath_d.o
myprint_d.o:myprint.c gcc -c -fPIC myprint.c -o myprint_d.o libhello.a: mymath.o myprint.o ar -rc libhello.a mymath.o myprint.o
mymath.o : mymath.c gcc -o mymath.o -c mymath.c
myprint.o: myprint.c gcc -o myprint.o -c myprint.c .PHONY:output
output: mkdir -p hello/lib mkdir -p hello/include cp -rf *.h hello/include cp -rf *.a hello/lib cp -rf *.so hello/lib
.PHONY:clean
clean: rm -rf *.o libhello.a output 此时我们即可以形成动态库也可以形成静态库. 然后此时我们make编译再make output将文件拷贝到指定目录中. 此时便把动态库也成功放入到lib路径下了.
此时我们便可以利用tar指令打包发送到网上然后让别人使用了。
如何使用编写的动态库
指定路径搜索(不可行及原因)
首先静态库中的第一种拷贝到系统路径里这种方法一定是可行的.
第二种方法这条指令
gcc main.c -I ./hello/include/ -L ./hello/lib/ -lhello
我们首先要知道gcc默认使用的是动态链接即使用动态库. a.当库中只有静态库时gcc就只能针对该库进行静态链接. b.当动静态库同时存在时默认使用的就是动态库 c.如果动静态库同时存在强制使用静态库那就需要再上面指令后面加上 -static 表示的是摒弃优先使用动态库的原则而是直接使用静态库的方法. 代码如下 gcc main.c -I ./hello/include/ -L ./hello/lib/ -lhello -static 我们同样地利用上面那一条指令进行编译生成可执行程序后我们把可执行程序移动到上一级目录.然后运行它。 此时我们再运行发现报错了就是找不到这个共享的文件这是为什么呢、我们不是已经指定路径了吗为什么还找不到呢 我们要明白动态库是一个独立的文件动态库可以和可执行程序分批加载 而我们指定路径是给gcc指定查找的是告诉了gcc的动态库的路径。 当我们运行和加载的时候就和gcc没有关系了所以我们要告诉操作系统或者加载器 这个动态库的路径 如果此时新来一个进程也需要用相同的动态库操作系统只需要将物理内存中动态库数据经过页表映射到对应进程的地址空间 中的共享区的位置这样代码区的代码遇到动态库中的函数直接去共享区去找。 那为什么静态库不用呢 静态链接的一旦编译好就和库没有关系了因为已经把库中代码拷贝到自己写的C/C代码中了.即已经在可执行程序中了. 环境变量LD_LIBRARY_PATH 这个是库加载时搜索的路径.我们只需要把我们的库的路径导入到这个环境变量里面即可.
export LD_LIBRARY_PATH$LD_LIBRARY_PATH:你的库文件路径导入完成后此时我们便可以成功运行了 但这个方法有一个缺点就是每次退出后我们导入的这些环境变量就会清空下次还需要重新导入比较麻烦。
修改配置文件 我们既不想在系统中安装我们的库又想永久保存那该怎么办呢 我们只需要在/etc/ld.so.conf.d/路径下 随便创建一个文件.然后vim打开文件输入你动态库文件路径然后退出保存即可.
sudo vim /etc/ld.so.conf.d/mylib.conf然后输入你的库文件路径即可然后退出执行重新加载指令
sudo ldconfig 这样也可以照样正常运行了. 到这里动静态库就讲完了感谢您的阅读哦~