文章目录
- gcc/g++的使用
- 背景知识
- gcc与g++
- gcc的编译过程
- 预处理
- 编译
- 汇编
- 链接
- 函数库
- 自动化构建工具--make
- 三个时间
- 伪目标文件
- 其他表示方法
- mybin的推导过程
gcc/g++的使用
背景知识
GCC是一个开源的编译器套件,支持多种编程语言,并提供了广泛的语言特性和标准库支持。可在各种操作系统中运行。
GCC具有强大的代码优化能力,可以对生成的机器代码进行各种优化,以改善程序的性能。
编译过程:GCC的编译过程主要包括预处理、编译、汇编和链接几个阶段。
下面我们会对这几个过程展开论述;
gcc与g++
g++是gcc中专门用于编译C++代码的命令。实际上也是GCC的一个别名,只是g++默认将源文件视为C++代码进行编译,并启用C++相关的特性和标准库;GCC默认将源文件视为C代码进行编译。
gcc的编译过程
编译格式:
gcc [选项] 要编译的文件 [选项] [目标文件]
预处理
gcc的预处理是编译过程的第一步,主要完成:
宏展开:处理所有宏定义,并将宏调用处替换为相应的内容;
头文件展开:将所有#define 指令包含的文件插入到该指令位置,以便在编译时能够使用被包含文件中的定义和声明。
条件编译:处理所有的条件预编译指令,如#if、#endif、#else等,根据条件判断是否编译相应的代码块。
添加行号和文件名标识:在编译后的文件中添加行号和文件名标识,方便调试时定位错误。
指令:gcc –E [要编译的文件] –o [生成的目标文件]
我们可以查看下test.i:
编译
经过预处理过程后,就会将预处理后的文件编译成汇编语言代码了。
指令:gcc -S [源文件] -o [目标文件]
我们可以查看该文件的内容:汇编语言代码
汇编
gcc将汇编代码转换成机器语言指令(二进制代码),并生成目标文件。
指令:gcc -c [源文件] -o [目标文件]
查看二进制文件:将会是一堆字符
链接
gcc将各个目标文件和库文件进行链接,生成可执行文件或动态链接库。
指令:gcc [源文件] -o [可执行文件]
这里涉及到一个重要的概念:函数库
函数库
函数库是一种预先编写好的可重复使用的代码模块集合,通常包含了常用的函数、数据结构、算法等,像我们在C程序中总会包含一个<stdio.h>一样,包含了输入输出的相关函数;
函数库分为两种类型:
静态数据库:静态数据库在编译链接时被完整地复制到可执行文件中,成为可执行文件的一部分。当应用程序运行时,静态数据库的代码会被加载到内存中并直接执行。优点是执行速度快,但缺点是会增加可执行文件大小。
动态数据库:动态数据库在编译链接时只保留函数的引用,而不将库函数的代码复制到可执行文件中。当应用程序运行时,需要使用动态库函数的函数时,系统会根据函数的引用从动态函数库中加载相应的代码并执行。优点是节省了可执行文件的空间,但缺点是稍微降低了执行速度。
一般默认生成的文件调用的都是动态链接库:
若想调用静态库:
自动化构建工具–make
make是一种常见的自动化构建工具,用于管理软件项目的编译、测试和部署等任务。make工具基于一个名为makefile的文件,其中包含一系列规则和依赖关系,指定了如何从源代码生成可执行文件或其他目标文件。
要执行该操作,需要先创建一个makefile名的文件(文件名不可改),然后在这个文件内进行编辑:
依赖关系:用于描述目标文件和依赖文件之间的关系;当makefile执行时,会通过目标文件,使用对应的依赖方法;
依赖方法:用于指定生成目标文件的命令。可以使用各种编译器和工具链的命令来编译、链接和生成目标文件。
在Linux对应目录下,执行命令make,就能执行:
清除操作:
这里要注意:
三个时间
查看文件时间属性:stat [文件名]
在Linux系统中,每个文件都有三个与时间相关的属性,分别是:
Access:表示文件最后一次被访问的时间戳。当文件被读取、执行、或者作为输入给某个程序时,访问时间会被更新。
Modify:文件最后一次被修改的时间戳。当使用编辑器修改文件内容时,修改时间会更新。
Change:代表的是文件属性最后一次被改变的时间戳。当文件的属性进行修改时,更改时间会更新。
所以make会判断执行文件是不是最后一次被更新了,若没被更新,则不需执行依赖方法的命令。
伪目标文件
通过该指令,执行make指令时,就不会被限制;
这是在makefile中定义的一种特殊目标,它不代表实际的文件,而是用来表示一个动作或任务。
伪目标文件通常用于定义一些不生成文件的操作和指令。常用于清理临时文件、安装和卸载文件的目标文件上。
其他表示方法
mybin的推导过程
- 这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文
件。- 在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,
而对于所定义的命令的错误,或是编译不成功,make根本不理。- make只管文件的依赖性,即,如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起,