文章目录
一、Linux编译器——gcc/g++的使用
- gcc是编译C语言的工具
- g++是编译C++的工具,也可以编译C语言,因为C++是兼容C语言的。
gcc与g++的使用方法与原理是相同,本文以gcc为例
gcc [选项] 要编译的文件 [选项] [目标文件]
1. 编译流程概述
GCC/G++ 将源代码转换为可执行文件的过程分为四个阶段:
- 预处理(生成
.i
文件):
- 去注释
- 宏替换
- 头文件展开
- 条件编译
gcc -E mycode.c -o mycode.i
- 选项:
-E
:仅执行预处理。-o
:指定输出文件名
- 编译(生成
.s
汇编文件):将预处理后的代码转换为汇编语言。
gcc -S mycode.i -o mycode.s
- 选项:
-S
:编译到汇编语言(不汇编、不链接)
- 汇编(生成
.o
目标文件):将汇编代码转换为机器码。
gcc -c mycode.s -o mycode.o
- 选项:
-c
:编译到目标文件(机器码,未链接)。
注意:目标文件.o
不可以独立执行,尽管他已经是二进制文件了。
- 链接(生成可执行文件):将可重定位的目标二进制文件和库进行链接形成可执行程序。
💡:记忆小技巧:
- 当我们记不住-E、-S、-c选项时,看看键盘左上角的Esc键,另外注意S要大写。
- 记不住临时文件后缀?记住.iso即可,它也是镜像文件的后缀。
2. 静态链接与动态链接
2.1 什么是库?
我们都知道,头文件.h中提供的是方法声明。那么,真正的方法在哪里呢?
没错,就是在库中:
头文件 + 库 + 你的代码 = 你的软件
库:经过一定的翻译,然后打包的源文件。
为什么要翻译打包?
- 只需提供一个文件即可,避免了提供太多的源文件
- 达到隐藏源文件的目的
2.2 目标文件与库是如何链接的呢?
- 动态链接:在可执行文件中保留动态库的引用信息,在可执行文件运行时由系统跳转加载到动态库中执行。
- 静态链接:将静态库的代码直接拷贝到可执行文件中,一般静态链接的可执行文件大小会比较大
从这两种链接的原理我们可以发现:
- 动态库不能缺失,一旦对应的动态库缺失,会导致很多的程序都无法正常运行。
- 通过静态链接生成点的程序将不再依赖静态库。
注意:在Linux中,默认的链接方式是动态链接
如果需要静态链接的方式,使用选项-static
来提供静态库:
gcc mycode.c -o mytest -static
其实-static
的本质就是改变优先级
💡:
- 如果没有静态库,还要使用-static是不行的
- 如果没有动态库,只有静态库,gcc会自动使用静态库
- 链接的方式不一定是纯的静态链接或者动态链接,也可以是混合链接。
2. 动态库vs静态库
动态库:
- 优点:由于动态库是共享库,可以有效的节省资源(磁盘空间、内存空间、网络空间等)
- 缺点:一旦丢失,会导致各个程序瘫痪
静态库:
- 优点:不依赖库,程序可以独立运行
- 缺点:体积大,更加消耗资源
二、Linux项目自动化构建工具——make/Makefile
- make:是一个命令
- makefile:是一个当前目录下的定义构建规则的文本文件,主要由依赖关系和依赖方法组成。
1. 使用方法
基本规则结构
target: dependencies # 目标对象与依赖对象(依赖关系)
[tab] command # 依赖方法必须以 Tab 开头(非空格)
示例:编译 hello.c 生成可执行文件 hello
hello: hello.c # 目标:hello,依赖:hello.c
gcc hello.c -o hello # 命令:编译命令
2. makefile的自动化推导
我们来输入以下内容:
结果:
可以发现:makefile的编译顺序与我们书写的顺序是无关的,它会按照我们书写的第一个目标文件为目标,自动化推导出正确的顺序,生成目标文件。
makefile以第一个目标文件为默认目标文件,使用时只需make即可。其余目标文件使用时均需要make+[目标文件]
3. 如何反复编译?
现在我们只需要输入make,就可以完成编译生成可执行程序了。
但当我们再次输入make,却报错了,为什么呢?
- 实在是没有必要编译多次,因此提高了编译效率。
3.1 使用.PHONY:
伪目标
怎么做到的呢?
make会根据源文件和目标文件的新旧,判定是否需要重新执行依赖关系进行编译。
只有可执行文件的修改时间比源文件老,才会重新编译。
所以,依赖关系不一定总是执行的!
若是想让依赖关系总是执行,可以使用.PHONY:
伪目标
.PHONY:让make忽略源文件和可执行目标文件的时间对比
.PHONY:
伪目标一般用作项目清理:
这样我们只需要输入make clean
,就可以快速完成项目清理了。
3.2 修改时间
- stat命令可以查看文件时间
- Access:上次的访问时间
- Modify:上次修改内容的时间
- Change:上次修改属性的时间
记忆小技巧💡:ACM时间
连锁反应:修改Modify,Change也会改变(文件大小变化)
touch + [已存在的文件]
,更新时间
如果不加选项,就会更新ACM时间
选项:
- -a:更新Access时间
- -c:更新Change时间
- -m:更新Modify时间
4. 自动变量
常用自动变量:
$@
目标文件名$^
依赖文件名
依据依赖关系自动匹配
示例:
另外,@+依赖方法
可以取消回显