一、GCC编译器
1.GCC编译器的介绍
◼ GCC 原名为 GNU C语言编译器(GNU C Compiler) ◼ GCC(GNU Compiler Collection,GNU编译器套件)是由 GNU 开发的编程语言
译器。GNU 编译器套件包括 C、C++、Objective-C、Java、Ada 和 Go 语言前
端,也包括了这些语言的库(如 libstdc++,libgcj等)
◼ GCC 不仅支持 C 的许多“方言”,也可以区别不同的 C 语言标准;可以使用命令行
选项来控制编译器在翻译源代码时应该遵循哪个 C 标准。例如,当使用命令行参数
-std=c99
启动 GCC 时,编译器支持 C99 标准。
◼ 安装命令 sudo apt install gcc g++ (版本 > 4.8.5)
◼ 查看版本 gcc/g++ -v/–version
2.GCC的工作流程
预处理去掉注释,将头文件复制到源代码,宏替换。.i为文本代码, 目标代码为2进制指令
3、用GCC编译来编译C程序
kekecoder@kekecoder-virtual-machine:~/Linux/lesson03$ gcc test.c -o app //生成目标文件
kekecoder@kekecoder-virtual-machine:~/Linux/lesson03$ ls
app test test.c
kekecoder@kekecoder-virtual-machine:~/Linux/lesson03$ ./app //运行程序
hello, GCC!!!
hello, GCC!!!
hello, GCC!!!
kekecoder@kekecoder-virtual-machine:~/Linux/lesson03$
4、GCC常见指令
二、静态库的制作和使用
1.静态库的制作
◼ 命名规则:
◆ Linux : libxxx.a
lib : 前缀(固定)
xxx : 库的名字,自己起
.a : 后缀(固定)
◼ 静态库的制作:
◆ (1)gcc 获得 .o 文件
◆ (2)将 .o 文件打包,使用 ar 工具(archive)
ar rcs libxxx.a xxx.o xxx.o
r – 将文件插入备存文件中
c – 建立备存文件
s – 索引
◆(1) gcc 获得 .o 文件
kekecoder@kekecoder-virtual-machine:~/Linux/lesson04/calc$ ls
add.c div.c head.h main.c mult.c sub.c
kekecoder@kekecoder-virtual-machine:~/Linux/lesson04/calc$
kekecoder@kekecoder-virtual-machine:~/Linux/lesson04/calc$ tree
.
├── add.c
├── div.c
├── head.h
├── main.c
├── mult.c
└── sub.c
0 directories, 6 files
kekecoder@kekecoder-virtual-machine:~/Linux/lesson04/calc$ gcc -c add.c mult.c div.c sub.c
kekecoder@kekecoder-virtual-machine:~/Linux/lesson04/calc$ tree
.
├── add.c
├── add.o
├── div.c
├── div.o
├── head.h
├── main.c
├── mult.c
├── mult.o
├── sub.c
└── sub.o
0 directories, 10 files
kekecoder@kekecoder-virtual-machine:~/Linux/lesson04/calc$
◆(2) 将 .o 文件打包,使用 ar 工具(archive)
kekecoder@kekecoder-virtual-machine:~/Linux/lesson04/calc$ ar rcs libcalc.a add.o sub.o mult.o div.o
kekecoder@kekecoder-virtual-machine:~/Linux/lesson04/calc$ tree
.
├── add.c
├── add.o
├── div.c
├── div.o
├── head.h
├── libcalc.a
├── main.c
├── mult.c
├── mult.o
├── sub.c
└── sub.o
0 directories, 11 files
kekecoder@kekecoder-virtual-machine:~/Linux/lesson04/calc$
最终生成libcalc.a
2.静态库的使用
kekecoder@kekecoder-virtual-machine:~/Linux/lesson05/library$ gcc main.c -o app -I ./include/ -L ./lib/ -l suanshu//返回上次目录找头文件,导入头文件 -L指定库路径 -l指定库名称
kekecoder@kekecoder-virtual-machine:~/Linux/lesson05/library$ tree
.
├── app
├── include
│ └── head.h
├── lib
│ └── libsuanshu.a
├── main.c
└── src
├── add.c
├── add.o
├── div.c
├── div.o
├── mult.c
├── mult.o
├── sub.c
└── sub.o
3 directories, 12 files
kekecoder@kekecoder-virtual-machine:~/Linux/lesson05/library$ ./app 运行app
a = 20, b = 12
a + b = 32
a - b = 8
a * b = 240
a / b = 1.666667
kekecoder@kekecoder-virtual-machine:~/Linux/lesson05/library$
三、动态库的制作和使用
1、动态库的制作
◼ 命名规则:
◆ Linux : libxxx.so
lib : 前缀(固定)
xxx : 库的名字,自己起
.so : 后缀(固定)
在Linux下是一个可执行文件
◼ 动态库的制作:
◆ gcc 得到 .o 文件,得到和位置无关的代码
gcc -c –fpic/-fPIC a.c b.c
◆ gcc 得到动态库
gcc -shared a.o b.o -o libcalc.so
kekecoder@kekecoder-virtual-machine:~/Linux/lesson06/calc$ gcc -shared *.o -o libcalc.so
kekecoder@kekecoder-virtual-machine:~/Linux/lesson06/calc$ tree
.
├── add.c
├── add.o
├── div.c
├── div.o
├── head.h
├── libcalc.so
├── main.c
├── mult.c
├── mult.o
├── sub.c
└── sub.o
0 directories, 11 files
kekecoder@kekecoder-virtual-machine:~/Linux/lesson06/calc$ ll
总用量 56
drwxrwxr-x 2 kekecoder kekecoder 4096 8月 13 16:25 ./
drwxrwxr-x 4 kekecoder kekecoder 4096 8月 12 16:20 …/
-rw-rw-r-- 1 kekecoder kekecoder 80 8月 12 16:20 add.c
-rw-rw-r-- 1 kekecoder kekecoder 1232 8月 13 16:13 add.o
-rw-rw-r-- 1 kekecoder kekecoder 94 8月 12 16:20 div.c
-rw-rw-r-- 1 kekecoder kekecoder 1240 8月 13 16:13 div.o
-rw-rw-r-- 1 kekecoder kekecoder 189 8月 12 16:20 head.h
-rwxrwxr-x 1 kekecoder kekecoder 7624 8月 13 16:25 libcalc.so*
-rw-rw-r-- 1 kekecoder kekecoder 306 8月 12 16:20 main.c
-rw-rw-r-- 1 kekecoder kekecoder 85 8月 12 16:20 mult.c
-rw-rw-r-- 1 kekecoder kekecoder 1240 8月 13 16:13 mult.o
-rw-rw-r-- 1 kekecoder kekecoder 85 8月 12 16:20 sub.c
-rw-rw-r-- 1 kekecoder kekecoder 1232 8月 13 16:13 sub.o
kekecoder@kekecoder-virtual-machine:~/Linux/lesson06/library$ tree
.
├── include
│ └── head.h
├── lib
│ └── libcalc.so
├── main.c
└── src
├── add.c
├── div.c
├── mult.c
└── sub.c
3 directories, 7 files
kekecoder@kekecoder-virtual-machine:~/Linux/lesson06/library$
2、动态库的使用(需要加入绝对路径)
02 / 工作原理
◼ 静态库:GCC 进行链接时,会把静态库中代码打包到可执行程序中
◼ 动态库:GCC 进行链接时,动态库的代码不会被打包到可执行程序中
◼ 程序启动之后,动态库会被动态加载到内存中,通过 ldd (list dynamic
dependencies)命令检查动态库依赖关系
◼ 如何定位共享库文件呢?
当系统加载可执行代码时候,能够知道其所依赖的库的名字,但是还需要知道绝对路
径。此时就需要系统的动态载入器来获取该绝对路径。对于elf格式的可执行程序,是
由ld-linux.so来完成的,它先后搜索elf文件的 DT_RPATH段 ——> 环境变量
LD_LIBRARY_PATH ——> /etc/ld.so.cache文件列表 ——> /lib/,/usr/lib
目录找到库文件后将其载入内存。
kekecoder@kekecoder-virtual-machine:~/Linux/lesson06/library$ export LD_LIBRARY_PATH=
L
D
L
I
B
R
A
R
Y
P
A
T
H
:
/
h
o
m
e
/
k
e
k
e
c
o
d
e
r
/
L
i
n
u
x
/
l
e
s
s
o
n
06
/
l
i
b
r
a
r
y
/
l
i
b
k
e
k
e
c
o
d
e
r
@
k
e
k
e
c
o
d
e
r
−
v
i
r
t
u
a
l
−
m
a
c
h
i
n
e
:
/
L
i
n
u
x
/
l
e
s
s
o
n
06
/
l
i
b
r
a
r
y
LD_LIBRARY_PATH:/home/kekecoder/Linux/lesson06/library/lib kekecoder@kekecoder-virtual-machine:~/Linux/lesson06/library
LDLIBRARYPATH:/home/kekecoder/Linux/lesson06/library/libkekecoder@kekecoder−virtual−machine: /Linux/lesson06/library echo
L
D
L
I
B
R
A
R
Y
P
A
T
H
:
/
h
o
m
e
/
k
e
k
e
c
o
d
e
r
/
L
i
n
u
x
/
l
e
s
s
o
n
06
/
l
i
b
r
a
r
y
/
l
i
b
k
e
k
e
c
o
d
e
r
@
k
e
k
e
c
o
d
e
r
−
v
i
r
t
u
a
l
−
m
a
c
h
i
n
e
:
/
L
i
n
u
x
/
l
e
s
s
o
n
06
/
l
i
b
r
a
r
y
LD_LIBRARY_PATH :/home/kekecoder/Linux/lesson06/library/lib kekecoder@kekecoder-virtual-machine:~/Linux/lesson06/library
LDLIBRARYPATH:/home/kekecoder/Linux/lesson06/library/libkekecoder@kekecoder−virtual−machine: /Linux/lesson06/library tree
.
├── include
│ └── head.h
├── lib
│ └── libcalc.so
├── main
├── main.c
└── src
├── add.c
├── div.c
├── mult.c
└── sub.c
3 directories, 8 files
kekecoder@kekecoder-virtual-machine:~/Linux/lesson06/library$ ldd main
linux-vdso.so.1 (0x00007ffc4e7e1000)
libcalc.so => /home/kekecoder/Linux/lesson06/library/lib/libcalc.so (0x00007fc16c3bc000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc16bfcb000)
/lib64/ld-linux-x86-64.so.2 (0x00007fc16c7c0000)
kekecoder@kekecoder-virtual-machine:~/Linux/lesson06/library$ ./main
a = 20, b = 12
a + b = 32
a - b = 8
a * b = 240
a / b = 1.666667
kekecoder@kekecoder-virtual-machine:~/Linux/lesson06/library$
四、静态库和动态库的区别
1、 静态库的优缺点
◼ 优点:
◆ 静态库被打包到应用程序中加载速度快
◆ 发布程序无需提供静态库,移植方便
缺点:
◆ 消耗系统资源,浪费内存
◆ 更新、部署、发布麻烦
2、动态库的优缺点
◼ 优点:
◆ 可以实现进程间资源共享(共享库)
◆ 更新、部署、发布简单
◆ 可以控制何时加载动态库
◼ 缺点:
◆ 加载速度比静态库慢
◆ 发布程序时需要提供依赖的动态库