GCC、静态库
- 1.2 GCC(1)gcc
- (1)常用命令
- (2) C程序编译过程
- (3)GCC工作流程
- 1.3 GCC(2)g++
- 1.3静态库的制作
- 1.5静态库的使用
- 1.6动态库的制作
- 1.7动态库加载失败的原因
- 1.8解决动态库加载失败的原因
- 1.9静态库与动态库对比
1.2 GCC(1)gcc
(1)常用命令
1、ctrl+l 清空屏幕
2、使用gcc编译
gcc xx.c -o app
解释:gcc + 文件名 + -o(用于指定编译后的文件名) + app(文件名)
3、生成可执行文件
./app
解释:运行刚刚编译出来的文件
如果gcc xx.c -o app不加-o,只有gcc xx.c
那么会生成一个a.out的可执行程序
(2) C程序编译过程
高级语言 编译 成汇编语言
汇编语言 汇编 成机器语言
机器语言 运行
(3)GCC工作流程
预处理:
1、展开头文件,将头文件中的内容复制进源代码
2、删除注释
3、对定义的宏做宏替换
指令: gcc test.c -E -o test.i
编译器:
将源代码编译成汇编代码(.s)
gcc test.i -S -o test.s
直接执行gcc test.c -S也会生成.s文件(就包含了预处理这一步)
汇编器:
将汇编代码汇编成目标代码(.O)
gcc test.s -c -o test.o
链接:
-c 生成目标代码 test.o,test.o 不是一个可执行程序。如果下一步需要继续链接成可执行程序,需要输入指令 gcc test.o -o test.out(这里直接将 .o 目标文件链接成可执行程序 test.out,可以有多个 .o 文件,这里只有一个)
所以整个直接 gcc test.c 包含了预处理,编译,汇编,链接成可执行文件4步。
1.3 GCC(2)g++
别管那么多,c就用gcc,cpp就应g++
-D使用示例:
#include <stdio.h>
#define PI 3.14
int main(){
int a = 10;
#ifdef DEBUG
printf("我不会爬树\n");
#endif // DEBUG
for(int i = 0; i < 3; ++i){
printf("hello,GCC\n");
}
return 0;
}
-Wall使用示例:
1.3静态库的制作
静态库实际上是将.c文件们打包。这些.c文件定义的函数,都在.h文件中申明。这样只需要把静态库和头文件给用户,用户就可以知道那些函数可以调用,但不清楚函数的具体实现。
-c使用示例:(生成.o文件)
制作静态库之前,首先需要把.c文件用gcc命令和 -c选项做成.o文件。 src目录下:gcc -c add.c div.c mult.c sub.c 是要报错的,因为找不到.h文件。如下所示。
所以实际上还要加上-I(大写i)选项,后面跟上.h所在的文件夹路径,告诉编译器去这个路径下找头文件:
gcc -c add.c div.c mult.c sub.c -I …/include/
注:.c文件在-c选项的前面还是后面无所谓
gcc add.c div.c mult.c sub.c -c -I …/include/
也可以。
ar命令的使用:(将.o文件打包成静态库)
ar rcs libsuanshi.a add.o div.o sub.o mult.o
移动命令:mv + 文件名 + 目的文件夹路径
1.5静态库的使用
参数选项
1、-I(大写i) :查找头文件的路径 (后面跟目录)
使用: -I 路径
例如:gcc main.c -o app -I ./include/
此时只找到了头文件,但没找到这些函数的定义,也就是静态库
2、-l(小写L):指定加载哪个库(后面跟的是库名字,不是库的文件名)
文件名:libcala.a
库名:calc
3、-L:指定到哪个文件夹下去找静态库(后面跟目录)
示例:
gcc main.c -o app -I ./include/ -l calc -L ./lib/
1.6动态库的制作
什么叫:与位置无关?
1、制作动态库:
生成与位置无关的.o文件
gcc -c -fpic add.c div.c sub.c mult.c
生成动态库
gcc -shared add.o sub.o mult.o div.o -o libcalc.so
2、使用动态库
与使用静态库一样,要指定头文件所在路径。动态库所在路径以及要使用的动态库名字(不是文件名字)
gcc main.c -o main -I ./include/ -l calc -L ./lib/
但这样使用会报错,运行main这个可执行文件的时候找不到动态库文件
1.7动态库加载失败的原因
ldd:list dynamic dependendcies 列出动态依赖库
后面的一串数组是内存地址,此时可以看到 libcalc.so这个动态库没有被找到。
每个程序就是一个进程,linux会为每个进程分配虚拟地址空间(DT_RPATH段)