静态库动态库和makefile

一:库的定义

    本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。由于windows和linux的本质不同,因此二者库的二进制是不兼容的。 Linux操作系统支持的函数库分为静态库和动态库,动态库又称共享库。Linux系统有几个重要的目录存放相应的函数库,如/lib    /usr/lib。

二、静态函数库、动态函数库

    静态库:  这类库的名字一般是libxxx.a;利用静态函数库编译成的文件比较大,因为整个函数库的所有数据都被整合进目标代码中,他的优点就显而易见了,即编译后的执行程序不需要外部的函数库支持,因为所有使用的函数都已经被编译进可执行文件了。当然这也会称为它的缺点,因为如果静态函数库改变了,那么你的程序必须重新编译,而且体积也较大。

    动态库: 这类库德名字一般是libxxx.so,动态库又称共享库;相对于静态函数库,动态函数库在编译的时候并没有被编译进目标代码中,你的程序执行到相关函数时才调用函数库里的相应函数,因此动态函数库所产生的可执行文件比较小。由于函数库没有被整合进你的程序,而是程序运行时动态申请并调用,所以程序的运行环境中必须提供相应的库。动态函数库的改变并不影响你的程序,所以动态函数库的升级比较方便。而且如果多个应用程序都要使用同一函数库,动态库就非常适合,可以减少应用程序的体积。

三:静态库和动态库的制作


静态库制作:

gcc -c file1.c -o file1.o

gcc -c file2.c -o file2.o

ar -cr  libname.a   file1.o  file2.o

-c :create的意思
-r :replace的意思,表示当前插入的模块名已经在库中存在,则替换同名的模块。如果若干模块中有一个模块在

库中不存在,ar显示一个错误信息,并不替换其他同名的模块。默认的情况下,新的成员增加在库德结尾处。

动态库制作:
gcc -shared  -fpic  -o libname.so  file1.c file2.c

-fpic:产生代码位置无关代码
-shared:生成共享库

四:举例使用静态库动态库

两个数相加c程序:
add.c
#include <stdio.h>

int add(int a,int b)
{
return a + b;
}

两个数相减c程序:
sub.c
#include <stdio.h>

int sub(int a,int b)
{
return a - b;
}

主程序:
main.c

#include <stdio.h>
#include "head.h"

int main(int argc,char *argv[])
{
int a,b;

if(argc < 3)
{
fprintf(stderr,"Usage : %s argv[1] argv[2].\n",argv[0]);
return -1;
}
a = atoi(argv[1]);
b = atoi(argv[2]);

printf("a + b = %d\n",add(a,b));
printf("a - b = %d\n",sub(a,b));

return 0;
}

头文件:
head.h

#ifndef _HEAD_H_
#define _HEAD_H_
extern int add(int a,int b);
extern int sub(int a,int b);
#endif


gcc -c add.c -o add.o
gcc -c sub.c -o sub.o      //编译生成可执行文件
ar -cr libas.a add.o sub.o    //制作静态库
ls
add.c  add.o  head.h  libas.a  main.c  sub.c  sub.o

gcc -shared -fpic -o libas.so add.c sub.c    //制作动态库

gcc main.c -L. -las -o test    //使用库文件


-L 指定函数库查找的位置,注意L后面还有'.',表示在当前目录下查找
-l则指定函数库名,其中的lib和.a(.so)省略。

./test 11 22

./test1: error while loading shared libraries: libas.so: cannot open shared object file: No such file or directory

注意:

1.当动态库和静态库同时存在的时候,gcc默认使用的是动态库。如果强制使用静态库则需要加-static选项支持。
2.链接静态库的可执行程序明显比链接动态库的可执行文件大。
3.动态库生成的可执行文件,test不能正常的运行。

五:让链接动态库的可执行程序正常运行

当系统加载可执行代码时候,能够知道其所依赖的库的名字,但是还需要知道绝对路劲。此时就需要系统动态载入器(dynamic  linker/loader)。

对于elf格式的可执行程序,是由ld-linux.so*来完成的,它先后搜索elf文件的DT_RPATH段---环境变量LD_LIBRARY_PATH、/etc/ld.so.cache文件列表、/usr/lib、/lib目录找到库文件后将其载入内存。

以下有三种解决方法

1.一种最直接的方法,就是把生成的动态库拷贝到/usr/lib或/lib中去。
sudo cp libas.so /usr/lib/

2.使用LD_LIBRARY_PATH环境变量,这个环境变量在ubuntu操作系统中默认没有,需要手动添加

export LD_LIBRARY_PATH=/home/zhangxing/zx4444/library:$LD_LIBRARY_PATH

3.动态在安装在其他目录下,如果想操作系统能找到它,可以通过一下步骤

<1>新建并编辑/etc/ld.so.conf.d/my.conf文件,加入库所在目录的路径
<2>执行ldconfig命令更新ld.so.cache文件

cd /etc/ld.so.conf.d/
sudo vim mylib.conf
/home/zhangxing/zx4444/library
sudo ldconfig

*需要注意的是只有第二种方法不需要用到sudo权限。

六:针对上例写一个简单地makefile

 + makefile ___________________________________________________________________________________
  1 LIB_NAME=as    //定义变量
  2 
  3 all: shared static    //总的目标依赖分目标,先执行shared和static目标
  4     rm -f *.o
  5 
  6 shared:
  7     gcc -shared -fpic -o lib${LIB_NAME}.so *.c    //使用变量要用到${}
  8 
  9 static:
 10     gcc -c *.c
 11     ar -rcs lib${LIB_NAME}.a *.o
 12 
 13 clean:
 14     rm -f *.o
 15     rm -f *.a *.so


*变量定义
VAR=test            定义变量VAR,强制赋值为test
VAR+=app         在VAR之前定义的值后面再追加app这个值
VAR?=testapp 如果之前VAR没有被定义,则定义并使用testapp;否则使用之前的值

*第一条目标为总目标
*依赖可以是文件(目录)或为其他目标
*动作可以是linux命令,动作的那一行第一个字必须是以TAB键开头

target: depend1 depend2
[TAB] action1
[TAB] action2

makefile使用基本命令:

make 找到makefile或Makefile文件执行的总目标

make clean 执行makefile文件中的clean目标

make -C directory 进入到directory文件夹中去执行总目标

make clean -c directory 进入到directory文件夹中执行clean目标

make -f comm_makefile 通过-f选项指定一个makefile文件

make VAR=value 给makefile传一个参数VAR,其值为value

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值