😁作者:日出等日落
🔔专栏:Linux
当你的希望一个个落空,你也要坚定,要沉着! —— 朗费罗
前言
gcc/g++是一个编译器
那么gcc将如何实现呢?
格式 gcc [选项] 要编译的文件 [选项] [目标文件]
📘程序的翻译
程序编译分为四个过程:
1.预处理 2.编译 3.汇编 4.链接
- 预处理(头文件展开,条件编译,宏替换,去注释等)
- 编译(c语言汇编语言)
- 汇编(汇编->可重定位目标二进制文件,不可以被执行的,bin.obj)只把我们自己的代码进行翻译形成二进制目标文件
- 链接(将我们这自己形成的.obj文件和库文件某种合并,形成可执行程序)
🖍编译过程
- 预处理功能主要包括宏定义,文件包含,条件编译,去注释等。
- 预处理指令是以#号开头的代码行。
- 实例: gcc –E hello.c –o hello.i
- 选项“-E”,该选项的作用是让 gcc 在预处理结束后停止编译过程。
- 选项“-o”是指目标文件,“.i”文件为已经过预处理的C原始程序。
下面我来详细演示具体实现:
这是myfile.c文件中写的C语言程序
如何直接生成可执行程序呢?
gcc 文件名 可以将文件直接编译成一个a.out的可执行程序
当需要生成一个需要由指定文件名的可执行程序如何操作呢?
-o为目标文件
具体过程:
“.i”文件为已经过预处理的C原始程序
“-E”,该选项的作用是让 gcc 在预处理结束后停止编译过程。
“-S”选项来进行查看,该选项只进行编译而不进行汇编,生成汇编代码。
汇编阶段是把编译阶段生成的“.s”文件转成目标文件“.o”的二进制目标代码
在成功编译之后,就进入了链接阶段。
📘动态库和静态库
1.库分为静态库(专门让编译器,对用户的程序进行静态链接的)和动态库(专门让编译器, 对用户的程序进行动态链接的)
2.静态库和静态链接:链接的时候,如果是静态链接,找到静态库,拷贝静态库中的我所需要的代码到我自己的可执行程序中
3.动态库和动态链接:链接的时候,如果是动态链接,找到动态库,拷贝动态库中的我所需要的代码的地址到我自己的可执行程序中相关的位
4.静态链接成功:我们的程序,不依赖任何库,自己就可以独立运行
5.动态链接成功:我们的程序,还是依赖动态库,一旦动态库缺失,我们的程序便无法运行!
6.静态库,因为自身拷贝的问题,比较浪费空间
7.动态库:因为可以做到被大家共享方法,所以真正的实现永远都是在库中,程序内部只有地址,比较节省空间
8.静态库vs动态库: Linux默认使用的是动态链接和动态库!1.静态库: libXXXXXX.a
2.动态库: libXXXXXX.so
静态链接
综上总结:
- -E 只激活预处理,这个不生成文件,你需要把它重定向到一个输出文件里面
- -S 编译到汇编语言不进行汇编和链接
- -c 编译到目标代码
- -o 文件输出到 文件
- -static 此选项对生成的文件采用静态链接
Linux项目自动化构建工具-make/Makefile
- makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编 译,极大的提高了软件开发的效率。
- make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命 令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一 种在工程方面的编译方法。
- make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建。
依赖关系
上面的文件 myfile ,它依赖 myfile.o
myfile.o , 它依赖 myfile.s
myfile.s , 它依赖 myfile.i
myfile.i , 它依赖 myfile.c
依赖方法
上面文件的指令就是依赖方法
clean:换行后删除语句
但是一般我们这种clean的目标文件,我们将它设置为伪目标
用 .PHONY 修饰,伪目标的特性是,总是被执行的。
使用make不成功的常见原因及解决方法
当你文件已经是最新版本时,系统就认为你不需要在进行make操作就会报这样的报错
我们可以通过时间来判断文件是否是最新的!
stat 文件名 可以查看时间
touch可以更改为最新时间