Linux 静态库与共享库
常用选项
-c
※ 预处理,只生成object文件,生成.o文件
-o
※ 生成目标文件,如果不带此选项,将生成a.out
-ansi
※ 支持 ansi C
-include file
※ 指定include file名,相当在代码中#include
-IDir
※ 指定头文件的路径,如果头文件不在系统的缺省路径下,用此选项
-I-
※ 取消 -IDir,编译器将不在上一个选项中搜索头文件
-g
※ 生成调试信息,否则 gdb 无法进行调试
-Wall
※ 生成警告信息
-O<0-3>
※ 大写字母O,非数字0,优化选项 默认为-O1, -O0无优化,级别越高
变异时间越长。
-static
※ 不使用动态连接库,一般把动态库直接结合到程序中,成为程序一部分,
所以生成代码比较大
-share
※ 使用动态库,所以代码比较小,当动态库文件不存在,程序将无法运行。
-fPIC
※ 生成独立性代码,与路径无关,一般配合-share使用。
建立共享库
首先回顾一下可执行文件生成到执行的过程,有4个步骤。
1 预处理:此阶段处理所有的预处理指令
2 编译:此阶段C文件生成目标文件
3 链接:此阶段是所有的目标文件和库共同链接来生成最终的可执行程序
4 执行:此阶段扫描共享库的引用,执行可执行文件
上述步骤表明,共享库在系统启动时加载器建立引用表(可以利用ldconfig命令进行更新),然后在文件执行时自动扫描该引用表获得调度入口(可以利用ldd命令检查所有引用共享库的入口),完成程序的所有链接,最后执行。
建立共享库和调用的过程:
一 编译位置无关代码。容易想象,共享库是在运行时加载,必然使用动态入口。相应
的命令是:
gcc -c -Wall -Werror -fpic tmp.o
二 根据目标文件创建一个共享链接库,相应的命令是:
gcc -shared -o tmp.so tmp.o
三 利用共享库建立可执行文件。
gcc -L/PathOfLib/tmp -Wall -o target dependence -ltmp
四 调用动态库有三种方法
1 更改LD_LIBRARY_PATH,设置临时路径。
export LD_LIBRARY_PATH=/home/username/foo:$LD_LIBRARY_PATH
2 使用gcc选项rpath,链接指定路径。
gcc -L/PathOfLib/ -Wl,-rpath=/PathOfLib/ -Wall -o target dependence -ltmp
3 与所有用户共享共享库。标准的共享库文件保存在/usr/lib或者/usr/local/lib.
sudo cp -rf /PathOfLib/libtmp.so /usr/lib
//复制到标准路径
sudo chmod 0755 /usr/lib/libtmp.so
//为所有用户添加权限
sudo ldconfig
//更新加载器
五 执行
./target
附:
通过ldconfig -p | grep tmp命令可以查看系统是否成功加载共享库。例如:
m@m-T6Series:~/Workspace/C/shareLib$ ldconfig -p | grep foo
libxgdfoo.so (libc6,x86-64) => /usr/lib/libxgdfoo.so
生成静态库的方法是很简单。这里也只作简单介绍:
gcc -c tmp.c -o tmp.o
ar crs libtmp.a tmp.o
因为静态库在链接的时候直接复制到程序中,所以直接才链接时指定库路径和库文件即可。可执行文件执行时跟相应的静态库无联系。具体操作如下:
gcc -o target dependence -L. -ltmp
//-L指定库路径为当前目录,-l指定库文件名称
运行
./target