开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第11天,点击查看活动详情
什么是编译
把程序的源代码翻译成CPU能够直接运行的机器代码,且编译永远是以一个源文件为单位,这样当我们对一个源文件修改时,只用编译该文件,则不用编译整个项目
注:常用的C/C++编译器除了gcc还有clang,msvc等。
什么是目标文件
经过编译后的二进制文件,后缀名为“.c” ,不同操作系统的目标文件类型并不相同如Windows是PE,而Linux是ELF,他们虽然互不兼容但在结构上非常相似,都是对二进制的封装。
gcc -c main.c 生成.o的文件,被称作目标文件,是一个二进制文件。文件格式是ELF,Windows上是PE。
readelf -h main.o 找到可执行文件的基本信息
readelf -S m 一系列的区块sections。.text .data等
注:目标文件虽然包含了编译之后的机器代码,但它并不能够直接执行,因为使用了尚未定义的函数如printf等,此类函数在主程序中仅是声明,编译器并不知道此类函数的定义,因此编译器只能将此类函数的跳转地址暂时先设为0随后在链接的时候再去修正它。
链接
其实是将编译之后的所有目标文件,连同用到的一些静态库、运行时库,组合拼装成一个独立的可执行文件,其中包括地址修正,此时,连接器会根据我们的目标文件或者静态库中的重定位表,找到那些需要被重定位的函数、全局变量,从而修正它们的地址,但我们在链接的时候,忘记提供必须的目标文件,那么链接器找不到声明函数的定义,于是报错“引用未定义”或者“符号未定义”。
makefile(make)
Makefile(make)是一个简单的构建工具,也可以用来自动生成文档,Makefile的核心是对“依赖”的管理。
makefile其实就是在构建一颗依赖树,你要构建最上方的这个目标就需要提供下面这些节点的文件,然后层层递归下去。用make指令可以根据依赖树递归的构建这个可执行文件。