编译:将源代码翻译成机器代码
在编译过程中使用gcc -c main.c 先编译main.c文件
然后使用gcc -c math.c 编译math.c 文件
在编译后会生成2个扩展为.o 的文件 main.o 和 math.o
.o文件是目标文件,该类型的文件在Linux通用格式是ELF,在windows下是PE, 这2个格式虽不兼容,但是结构类似,都是对二进制代码的封装
//main.c
#include <stdio.h>
int add(int a,int b); //一句声明
int main(){
printf("Hello");
int result = add(1,4); //在编译main.c的过程中不知道add函数具体是什么,但是有定义了声明,编译不会错
return result;
}
//math.c
int add(int a,int b){
return a+b;
}
可以使用一些命令查看elf的内容
readelf -h main.o 查看文件头
readelf -S main.o 查看段信息
objdump -s -d main.o 查看汇编指令
objdump -r main.o 查看重定位表
在编译main.c文件,编译器将add函数和printf函数的跳转地址暂时设置0,在后面的链接过程中修改
main.o里面有2个需要被重定位的函数printf和add
使用gcc main.o math.o -o main 链接得到可执行文件main
链接就是将编译好的目标文件连同用到的静态库、运行时库组合拼装成一个独立可执行的文件,包括将函数的跳转地址修正成正确的
如果你使用gcc main.o -o mian, 链接器找不到add函数的实现,报错undefined reference
makefile
makefile其实是构建一颗依赖树,使用make main命令执行
all: main
main: main.o math.o
gcc main.o math.o -o main
main.o: main.c
gcc -c main.c
math.o: math.c
gcc -c math.c
clean:
rm main main.o math.o