ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

使用gcc生成静态库和动态库

2019-10-11 16:01:22  阅读:270  来源: 互联网

标签:bin elf64 gcc x86 静态 生成 文件格式 answer 64


盘古开天辟地。我们写了个程序,想要给终端输出一些内容,不可避免地我们需要使用系统库,在我们写程序的过程中我们经常会碰到需要使用库的过程,无论是系统库还是第三方库,我们统称为lib库。

而库的链接分为两种,分别有静态库和动态库。

1. 静态库

静态库可以看作一堆的目标文件的集合,可能包含了很多函数的实现。在linux最常用的C语言静态库libc位于/usr/lib/libc.a,它由成百上千个C语言程序,比如输入输出有printf.o,scanf.o,文件操作有fread.o,fwrite.o等等。把这些零散的文件提供给使用者会造成不便,于是通常人们用ar压缩程序将这些目标文件压缩到一起,然后对这些文件进行编号和索引,最后形成了libc.a这个文件。

运行命令查看其中包含的内容,然后过滤查看fread

$  ar -t /usr/lib/x86_64-linux-gnu/libc.a | grep fread
iofread.o
__freading.o
__freadable.o
iofread_u.o
fread_chk.o
fread_u_chk.o

如果我们要在其中寻找printf.o文件可以使用命令

$ objdump -t /usr/lib/x86_64-linux-gnu/libc.a | grep printf.o
vfprintf.o:     文件格式 elf64-x86-64
vprintf.o:     文件格式 elf64-x86-64
reg-printf.o:     文件格式 elf64-x86-64
fprintf.o:     文件格式 elf64-x86-64
printf.o:     文件格式 elf64-x86-64
snprintf.o:     文件格式 elf64-x86-64
sprintf.o:     文件格式 elf64-x86-64
asprintf.o:     文件格式 elf64-x86-64
dprintf.o:     文件格式 elf64-x86-64
vfwprintf.o:     文件格式 elf64-x86-64
fxprintf.o:     文件格式 elf64-x86-64
iovsprintf.o:     文件格式 elf64-x86-64
fwprintf.o:     文件格式 elf64-x86-64
swprintf.o:     文件格式 elf64-x86-64
vwprintf.o:     文件格式 elf64-x86-64
wprintf.o:     文件格式 elf64-x86-64
vswprintf.o:     文件格式 elf64-x86-64
vasprintf.o:     文件格式 elf64-x86-64
iovdprintf.o:     文件格式 elf64-x86-64
vsnprintf.o:     文件格式 elf64-x86-64
obprintf.o:     文件格式 elf64-x86-64

可以看到printf.o文件就在其中。

假如以我们写的helloworld.c程序为例

#include <stdio.h>

int main(int argc, char *argv[])
{
    printf("Hello,World!\n");
    return 0;
}

默认情况下直接运行

$ gcc helloworld.c -o helloworld

会进行动态链接,我们查看生成的文件大小

$ ls -l helloworld
-rwxr-xr-x 1 gnc gnc 8304 10月 11 15:06 helloworld

可以看到大小为8303bytes,我们使用选项-static来使gcc进行静态链接:

$ gcc -static helloworld.c -o helloworld

查看大小

$ ls -l helloworld
-rwxr-xr-x 1 gnc gnc 844704 10月 11 15:09 helloworld

可以看到大小显著变大。

2. 动态库

静态链接好处就是链接完成以后,运行程序不需要原来的支持库,但缺点是文件大小较大,并且更新困难。

所以出现了动态链接,也就是不要静态地进行链接,而是等到动态运行时再进行链接。动态链接的符号定位是发生在运行时首先进行地址空间分配,然后再来运行程序。

具体的链接过程也比较复杂,我们只需要知道如何来创建这种动态库即可。

3. gcc创建静态和动态库

源文件add.c

/* add.h */
void setSummand(int summand);
int  add(int summand);

/* add.c */
#include <stdio.h>

int gSummand;


void setSummand(int summand) {
  gSummand = summand;
}

int add(int summand) {
  return gSummand + summand;
}

void __attribute__ ((constructor)) initLibrary(void) {
 //
 // Function that is called when the library is loaded
 //
    printf("Library is initialized\n"); 
    gSummand = 0;
}
void __attribute__ ((destructor)) cleanUpLibrary(void) {
 //
 // Function that is called when the library is »closed«.
 //
    printf("Library is exited\n"); 
}

源文件answer.c

/* answer.h */
int answer();

/* answer.c */
#include "add.h"

int answer() {

  setSummand(20);
  return add(22);  // Will return 42 (=20+22)

}

源文件main.c

#include <stdio.h>
#include "add.h"
#include "answer.h"

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

  setSummand(5);

  printf("5 + 7 = %d\n", add(7));

  printf("And the answer is: %d\n", answer());

  return 0;
}

然后我们创建目录.bin/static./bin/shared

完成以后的目录结构如下

$ tree
.
├── add.c
├── add.h
├── answer.c
├── answer.h
├── bin
│   ├── shared
│   └── static
└── main.c

3 directories, 5 files

我们运行命令生成目标文件

$ gcc -c       main.c        -o bin/main.o

# 静态库
$ gcc -c       add.c    -o bin/static/add.o
$ gcc -c       answer.c -o bin/static/answer.o

# 动态库
gcc -c -fPIC add.c    -o bin/shared/add.o
gcc -c -fPIC answer.c -o bin/shared/answer.o

3.1 创建静态库

运行命令

$ ar rcs bin/static/libtq84.a bin/static/add.o bin/static/answer.o

将两个目标文件打包压缩为一个静态库文件。

静态链接

$ gcc bin/main.o -Lbin/static -ltq84 -o bin/static-main

运行

$ ./bin/static-main 
Library is initialized
5 + 7 = 12
And the answer is: 42
Library is exited

3.2 创建动态库

运行命令

$ gcc -shared bin/shared/add.o bin/shared/answer.o -o bin/shared/libtq84.so

然后进行动态链接

$ gcc  bin/main.o -Lbin/shared -ltq84 -o bin/use-shared-library

运行

$ ./bin/use-shared-library 
./bin/use-shared-library: error while loading shared libraries: libtq84.so: cannot open shared object file: No such file or directory

会提示找不到动态链接库,我们需要修改LD_LIBRARY_PATH变量来指向我们的动态库路径

export LD_LIBRARY_PATH=$(pwd)/bin/shared

然后再运行

./bin/use-shared-library 
Library is initialized
5 + 7 = 12
And the answer is: 42
Library is exited

就可以了,当然你也可以选择将该动态库放置到路径/usr/lib下,运行下面的命令

sudo mv bin/shared/libtq84.so /usr/lib
sudo chmod 755 /usr/lib/libtq84.so

标签:bin,elf64,gcc,x86,静态,生成,文件格式,answer,64
来源: https://www.cnblogs.com/cporoske/p/11654730.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有