【Linux玩物志】Linux环境开发基本工具使用(2) ——gcc/g++与make/makefile

W…Y 2024-06-12 15:07:04 阅读 86

W...Y的主页 😊

代码仓库分享💕 

 


前言:前面我们了解了一些Linux工具——yum、vim,并且普及了一些他们的一些指令。今天我们继续了解Linux的工具gcc/g++、make与makefile,以及调试器gbd。

目录

Linux编译器-gcc/g++使用

背景知识

gcc与g++如何完成

预处理

编译

 汇编

​编辑连接

函数库

gcc选项

Linux项目自动化构建工具-make/Makefile

背景

理解

 依赖关系

依赖方法

原理


Linux编译器-gcc/g++使用

背景知识

我们都在vs上编译过代码,vs上是集成开发环境,所以我们只需要ctrl+F5就可以一键运行代码,但是代码从开始到运行,是怎么进行的呢?

1. 预处理(进行宏替换)

2. 编译(生成汇编)

3. 汇编(生成机器可识别代码)

4. 连接(生成可执行文件或库文件)

gcc与g++如何完成

格式 gcc [选项] 要编译的文件 [选项] [目标文件]

那gcc与g++有什么不同的呢?我们先创建两个不同的文件。

分别在.c文件中使用vim写C语言代码,在.cpp中写C++代码。然后进行编译。

.c文件既可以使用g++编译也可以使用gcc编译。

 而.cpp文件不能使用gcc进行编译,只能使用g++,这就是其中区别。

往下我们只使用gcc指令。

预处理

在预处理对应的功能有很多:

1.头文件展开:所谓的头文件展开本质是在预处理的时候将头文件内容拷贝至源文件。

2.去掉注释

3.宏替换

4.条件编译

当我们想要看到其中的预处理代码时,我们可以使用gcc -E + 需要预处理文件。

 

 我们使用vim将预处理的test.i文件打开就可以看到预处理的内容:

展开后的内容很多,这里我只截取一小部分!

选项“-E”,该选项的作用是让 gcc 在预处理结束后停止编译过程。

选项“-o”是指目标文件,“.i”文件为已经过预处理的C原始程序。

编译

在这个阶段中,gcc 首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,gcc 把代码翻译成汇编语言。

用户可以使用“-S”选项来进行查看,该选项只进行编译而不进行汇编,生成汇编代码。

如果我们想要看汇编代码即可使用gcc -S+需要生成汇编文件。

 

我们既可以从头test.c开始进行转汇编,也可以从刚刚生成的.i文件开始。

 汇编

汇编阶段是把编译阶段生成的“.s”文件转成目标二进制文件,但是这里的二进制文件不能被计算机执行,因为他少一步链接。

我们使用gcc –c + 需要生成二进制的文件。

连接

在成功编译之后,就进入了链接阶段。最终直接生成可执行程序。

指令:gcc + 文件

函数库

我们的C程序中,并没有定义“printf”的函数实现,且在预编译中包含的“stdio.h”中也只有该函数的声明,而没有定义函数的实现,那么,是在哪里实“printf”函数的呢?

最后的答案是:系统把这些函数实现都被做到名为 libc.so.6 的库文件中去了,在没有特别指定时,gcc 会到系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到 libc.so.6 库函数中去,这样就能实现函

数“printf”了,而这也就是链接的作用

函数库一般分为静态库和动态库两种

刚才我们生成的mytest可执行程序就使用了C库:

 不同操作系统下动静态库文件结尾:

Linux Windows
动态库 .so .dll
静态库 .a .lib

 所以我们libc.so.6中去掉前缀lib,去掉后缀.so,只剩下一个c,证明我们使用的mytest程序调用了C库。

 在Linux下都有动态库与静态库,而动静态都是文件。动态库的优点是比较节省资源,不会出现太多重复代码,动态库缺点是依赖性比较强,一但库丢失,所有使用这个库的程序都无法运行,与动态库连接就是动态连接。

静态库的优点是不依赖库,同类型平台中都可以直接运行。缺点就是可执行程序体积比较大,浪费资源,与静态库连接就是静态链接。

我们可以使用ldd指令查看对应可执行程序的库情况:

我们刚才所生成的mytest可执行程序所使用的是动态连接。我们想让其使用静态连接就可以在gcc后面+ -static即可:

上述图证明我们缺少C静态库, 所以我们用yum进行安装:yum install -y glibc-static

 我们可以看出gcc默认的行为是动态连接。 

gcc选项

-E 只激活预处理,这个不生成文件,你需要把它重定向到一个输出文件里面

-S 编译到汇编语言不进行汇编和链接

-c 编译到目标代码

-o 文件输出到 文件

-static 此选项对生成的文件采用静态链接

-g 生成调试信息。GNU 调试器可利用该信息。

-shared 此选项将尽量使用动态库,所以生成文件比较小,但是需要系统由动态库.

-O0

-O1

-O2

-O3 编译器的优化选项的4个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高

-w 不生成任何警告信息。

-Wall 生成所有警告信息。 

Linux项目自动化构建工具-make/Makefile

背景

一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作

makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。

make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。

make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建。

理解

我们先简单使用一下:

先在当前有需要编译文件的目录下创建一个makefile文件(Makefile首字母大写也可以)。进入vim编译:

第一行叫做依赖关系,第二行叫做依赖方法!

保存退出后使用make即可生成mybin可执行程序。

 

 依赖关系

上面的文件 mybin ,它依赖 test.o

test.o , 它依赖 test.s

test.s , 它依赖 test.i

test.i , 它依赖 test.c

依赖方法

gcc hello.* -option hello.* ,就是与之对应的依赖关系 

上述的依赖关系我们可以理解为为什么要帮你,依赖方法指怎么帮你!

原理

make是如何工作的,在默认的方式下,也就是我们只输入make命令。

1. make会在当前目录下找名字叫“Makefile”或“makefile”的文件

2. 如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“test”这个文件,并把这个文件作为最终的目标文件。

3. 如果test文件不存在,或是test所依赖的后面的hello.o文件的文件修改时间要比hello这个文件新(可以用 touch 测试),那么,他就会执行后面所定义的命令来生成hello这个文件。

4. 如果test所依赖的test.o文件不存在,那么make会在当前文件中找目标为test.o文件的依赖性,如果找到则再根据那一个规则生成test.o文件。(这有点像一个堆栈的过程)

5. 当然,你的C文件和H文件是存在的啦,于是make会生成 test.o 文件,然后再用 test.o 文件声明make的终极任务,也就是执行文件test了。

6. 这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。

7. 在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make根本不理。

8. make只管文件的依赖性,即如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起,我就不工作啦。 

当我们使用make编译完成后再去使用make就会出现下图报错:

因为可执行程序是最新的,没有对test.c进行修改。只有我们进行修改test.c才可以进行make。或者我们把执行程序清理掉。

我们只需呀在makefile文件中加入clean即可:

 makefile在形成目标文件时默认从上到下扫描,默认形成的是第一个目标文件并且只形成一个。所以我们使用make时就执行mybin,而清理时必须用make clean。假设clean在第一行,那我们make时默认执行的是rm mybin,要想进行编译则使用make mybin指令。

那我们一直想重新编译该怎么办呢?在makefile中加入.PHONY,他是一个关键字,修饰目标文件使其成为伪目标。

 

这样我们就可以一直进行make编译操作。我们最好在clean时都加上伪目标:

我们也可以使用makefile中的语法进行简化。

$@代码目标文件,$^代表依赖文件列表。makefile也可以出现类似宏定义的规则,例如 cc = gcc,在后面的内容中我们可以将gcc替换为$(cc)。

以上就是我们这次的全部内容,感谢大家观看! 



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。