目录
第七步:编译test.c并链接共享库libcommon.so
一、静态库的创建
1、确定库中函数的功能、接口
2、编写库源码hello.c
第一步:创建hello.c库源码如下:
#include <stdio.h>
void hello(void)
{
printf("hello world\n");
return 0;
}
第二步:编译生成目标文件 .c生成.o
gcc -c hello.c -Wall
第三步:创建静态库hello
ar crs libhello.a hello.o
/*
1、ar工具专门用来创建静态库,crs是对应的选项,用它来生成一个静态库文件;
2、libhello.a 是生成的库名称 hello.o是库中所包含的目标文件,
可以是一个.o文件也可以是多个.o文件;
3、linux中对静态库的名称要求:必须以lib开头,.a结尾,
.a表示这是一个静态库,中间表示其库名称,一般表示其功能。
*/
第四步:查看库中符号信息,使用nm工具来查看
nm libhello.a
第五步:编写应用程序test.c
#include <stdio.h>
void hello(void);//声明原形
int main()
{
hello();
return 0;
}
第六步:编译test.c并链接静态库libhello.a
gcc -o test test.c -L. -lhello
// -L 用来指定添加库的搜索路径,"."代表当前路径
// -l表示要链接哪个库,后面跟的是库名 hello
//编译器默认链接C库,在C库不需要路径,其他地方需要添加路径
第七步:运行程序
./test
//hello库中代码复制到程序test中,程序执行不需要在用到库
二、动态库/共享库的创建
特点:
1、程序不包含库中代码,尺寸小
2、多个程序可共享同一个库
3、程序运行时需要加载库
4、升级方便,无需重新编译程序
5、使用广泛
共享库创建:确定库中函数的功能、接口
第一步:编译库源码 hello.c bye.c
//hello.c
#include <stdio.h>
void hello(void)
{
printf("hello world\n");
return;
}
//bye.c
#include <stdio.h>
void hello(void)
{
printf("bye!\n");
return;
}
第二步:编译生成目标文件
gcc -c -fPIC hello.c bye.c -Wall
/*
PIC告诉编译器生成位置无关代码,
生成的hello.o和bye.o可以被加载到任意的地址执行,
而不是只能在固定地址执行,用相对寻址
*/
第三步:创建共享库common
gcc -shared -o libcommon.so.1 hello.o bye.o
/*
1、-share指定让gcc去创建一个共享库文件
2、共享库名一般以lib开头,".so"代表共享库,
后面一般会紧跟一个数字,数字一般代表库的版本,
这样可以在库中保留同一个库的不同版本
3、hello.o bye.o 表示目标文件名称
*/
第四步:为共享库创建链接文件
目的:让编译器编译时找到共享库
ln -s libcommon.so.1 libcommon.so
/*
1、ln 创建链接文件,分为硬链接和软链接。
相当于给目标文件 libcommon.so.1取别名为 libcommon.so
2、加-s表示创建的是软链接。libcommon.so是libcommon.so.1的快捷方式
3、libcommon.so.1:目标文件
4、libcommon.so:符号链接//要求:lib开头 .so结尾 中间是名称
*/
第五步:编写test.c文件
#include <stdio.h>
#include "common.h";//声明
int main()
{
hello();
bye();
return 0;
}
第六步:声明
创建一个头文件包含库
//common.h
#ifndef __COMMON_H__
#define __COMMON_H__
void hello(void);
void bye(void);
#endif
第七步:编译test.c并链接共享库libcommon.so
gcc -o test test.c -L. -lcommon
/*
与静态库相同,先找共享库,如果共享库不存在则找静态库,均没有则报错
*/
第八步:添加共享库的加载路径
三种方法:
1>直接将动态库文件拷贝到 /lib 或者 /usr/lib 中(一般推荐);
2>将动态库的路径声明到系统当中 (强烈推荐)
//1>打开配置文件 :
sudo vim /etc/ld.so.conf
//2>在该文件的下面添加一行:
/home/pig/
//绝对路径
//3>保存并退出后执行命令
sudo ldconfig
3>将动态库声明到环境变量中(慎用)
动态库所属的环境变量:LD_LIBRARY_PATH
我们在某个终端中执行以下命令:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/pig/ //:绝对路径
第九步:执行
./test
拓展
-shared:指定生成动态链接库。
-fPIC:表示编译为位置独立的代码,用于编译共享库。目标文件需要创建成位置无关码,
概念上就是在可执行程序装载它们的时候,它们可以放在可执行程序的内存里的任何地
方。
-Wl,options:把参数(options)传递给链接器ld。如果options中间有逗号,就将options
分成多个选项,然后传递给链接程序。
-static:指定生成静态链接库。
-c:只激活预处理、编译和汇编,也就是把程序做成目标文件(.o文件)。
-E:使用-E选项可以让GCC停止在预处理完成阶段(完成所有#define,#if,#include等替
换),输出到标准输出,除非指定-o选项,gcc不再做更多的处理。可使用-o选项生成
一个以i结尾的文件(GCC默认将.i文件看成是预处理后的C语言源代码)
-S :停止在汇编阶段,输出.s(汇编语言源码)但不调用as
-On(n=1,2,3) 使用编译选项-On来控制优化代码的生成,其中n是一个代表优化级别
的整数。通常来说,数字越大优化的等级越高,同时也就意味着程序的运行速度越快。
在linux下一般使用-O2选项,因为它在优化长度、编译时间和代码大小之间,取得了一
个比较理想的平衡点
-l:指定链接时需要的动态库。编译器查找动态连接库时有隐含的命名规则,即在给出
的名字前面加上lib,后面加上.so来确定库的名称。
-Wall:生成所有警告信息。
-ggdb:此选项将尽可能的生成gdb的可以使用的调试信息。
-g:编译器在编译的时候产生调试信息。
-I :将指定目标加入到头文件的搜索目录列表中
-L:表示要连接的库在当前目录中。