Linux开发工具【gcc/g++】

Linux开发工具之【gcc/g++】

上文我们已经学习了vim编辑器的相关操作和使用,已经可以在Linux下编写代码了,有了代码就需要编译运行,此时就需要用到Linux中的编译工具gcc/g++了,其中gccC语言的编译器,g++C++的编译器,下面我们一起来学习一下吧


文章目录:

  • Linux开发工具之【gcc/g++】
  • 1. Linux编译器gcc/g++使用
    • 1.1 目标文件
    • 1.2 预处理
    • 1.3 编译
    • 1.4 汇编
    • 1.5 链接
  • 2. 库
    • 2.1 动态库
    • 2.2 静态库
  • 3. 自动化构建工具make/Makefile
    • 3.1 概念引入
    • 3.2 Makefile文件
    • 3.3 make指令
    • 3.4 .PHONY伪目标
  • 4. sudo提权
    • 4.1 sudo使用
    • 4.2 sudo配置

1. Linux编译器gcc/g++使用

下面以gcc为例来进行讲解,学会了gccg++也自然不在话下,这两个编译器的选项都是通用的,上手比较简单

1.1 目标文件

将代码编译链接生成可执行程序,默认生成可执行文件a.out

gcc/g++ 源文件

Linux开发工具【gcc/g++】_第1张图片

当然也可以通过-o选项,来生成指定的可执行文件

-o 目标文件:生成指定目标文件

gcc/g++ -o 目标文件 源文件
gcc/g++ 源文件 -o 目标文件

Linux开发工具【gcc/g++】_第2张图片

注意:-o选项后必须跟要生成的目标文件,这个选项放在源文件前面或者后面都是可以的

1.2 预处理

在之前说到过,程序的翻译分为:预处理、编译、汇编、链接四个阶段,下面我们就通过gcc的学习来具体看看每个阶段都做了些什么

Linux开发工具【gcc/g++】_第3张图片

首先是预处理,主要功能包括包括宏定义,文件包含,条件编译,去注释等,经过预处理后文件的后缀为.i

通过-E选项,可以使编译器在执行完预处理后停下来,配合-o生成指定文件

gcc/g++ -E 源文件 -o 目标文件(.i)

Linux开发工具【gcc/g++】_第4张图片

Linux开发工具【gcc/g++】_第5张图片

1.3 编译

第二步是编译,在这个阶段gcc/g++会对代码进行语法分析、词法分析、语义分析、符号汇总等,然后将合法的代码转为汇编代码,经过编译后文件的后缀为.s

通过-S选项,可以使编译器在执行完编译后就停下来,配合-o生成指定文件

-S 源文件 -o 目标文件(.s)  //也可以直接从.i文件开始执行

Linux开发工具【gcc/g++】_第6张图片

Linux开发工具【gcc/g++】_第7张图片

1.4 汇编

第三步是汇编,这个阶段是将汇编代码转化为二进制,并生成符号表,也就是把编译阶段生成的.s文件转成目标文件,经过汇编后的文件后缀为.o

符号表相当于每个函数独自的地址,在Linux 中,C语言的符号表通常是 _函数名,如 _Add ,C++的符号表通常为 _Z函数名长度+函数名+参数1+参数2

通过 -c 选项,可以使 编译器在执行完汇编阶段后就停下来,配合-o生成指定文件

gcc/g++ -c 源文件 -o 目标文件(.o)  //也可以从.i/.s文件开始执行

二进制文件是elf格式,用vim直接查看是乱码,可以用readelf工具查看,没有的可以自行下载

Linux开发工具【gcc/g++】_第8张图片

Linux开发工具【gcc/g++】_第9张图片

1.5 链接

最后一步是链接,这个阶段会进行合并段表,符号表的合并和重定位等操作,会将程序运行所需的各种函数链接起来,包括与库函数的链接,Linux 中一般是动态链接,链接后生成可执行文件,默认为a.out,也可以自己指定

gcc/g++ 源文件 -o 目标文件  //也可以从.i/.s/.c文件开始执行

Linux开发工具【gcc/g++】_第10张图片

Linux开发工具【gcc/g++】_第11张图片

以上就是gcc/g++的全部讲解和操作了,希望对各位有帮助

2. 库

每种编程语言都有自己的库,比如c语言的stdiostdlib等,我们在调用库函数时,就是在调用标准库中的函数,Linux下C语言的标准库都在/usr/include路径下,这个文件就是C语言的动态库

Linux开发工具【gcc/g++】_第12张图片

2.1 动态库

动态库中的内容是被所有程序共享的,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,这样可以节省系统的开销。动态库一般后缀名为“.so”,如 libc.so.6 就是动态库。gcc 在编译时默认使用动态库。完成了链接之后,gcc 就可以生成可执行文件

Linux中默认使用动态链接,通过指令ldd可以列出一个程序所需要的动态链接库(动态链接库也称共享链接库)

ldd 文件名  //查看文件链接情况

Linux开发工具【gcc/g++】_第13张图片

这里libc.so.6就是动态链接的标志,其中lib是前缀,.so是后缀,去掉前后缀,最终为c,即为文件最终调用的库

file命令查看文件详细信息

file 文件名  //查看文件的详细信息

动态链接主要依赖不同函数在库中的位置信息进行调用,只有一份代码库,比较节省空间

举个生活中的例子帮助记忆:

  • 动态库就好像是网咖,全村的人都可以去网咖上网,还可以选择自己喜欢的机位和配置

2.2 静态库

静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件了。其后缀名一般为“.a,如果想采用 静态链接的方式编译程序,需要在编译时加上 -static 选项”

没有静态库可以自行下载

yum install -y glibc-static  //下载C语言静态库
yum install -y glibc-static libstdc++-static  //下载c++语言静态库

Linux开发工具【gcc/g++】_第14张图片

静态库名称为libXXX.a,其中lib是前缀,.a是后缀,去掉前后缀,就是最终调用的库

由于静态链接是直接讲所需代码拷贝到程序中,所以最终生成的文件相对动态链接会大很多

Linux开发工具【gcc/g++】_第15张图片

接着上面的例子:

  • 静态库就像是你觉得村里的网吧太远了,自己买了一台电脑放到家里玩(调用某个库),不过如果买了很多台,家里就没地方放了(空间不足)

总结

  • 库分为动态库和静态库,静态库让编译器对用户程序进行静态链接,动态库让编译器对用户程序进行动态链接
  • 静态库和静态链接:链接的时候,如果是静态链接,找到静态库,拷贝静态库中的所需要的实现功能的代码到自己的可执行程序中
  • 动态库和动态链接:链接的时候,如果是动态链接,找到动态库,拷贝动态库中的所需要的实现功能的代码的地址到自己的可执行程序中。
  • 静态链接成功:程序不依赖任何库,可以独立运行
  • 动态链接成功:程序依赖动态库,一旦动态库缺失,程序无法运行。一般的云服务器,默认的只有动态库

优缺点

动态库优点

  • 可以实现不同进程间的资源共享
  • 因为自身拷贝地址,相比静态库节省很大空间
  • 不调用函数时可以不加载动态库

动态库缺点

  • 需要调用函数,加载速度较慢
  • 程序依赖动态库,一旦动态库缺失,程序无法运行

静态库优点

  • 所需函数直接拷贝至程序中,运行速度快
  • 程序不依赖任何库,可以独立运

静态库缺点

  • 因为自身拷贝实现功能代码问题,浪费空间

3. 自动化构建工具make/Makefile

3.1 概念引入

  • makefile带来的好处就是—“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
  • make是一个命令工具,是一个解释makefile中指令的命令工具
  • make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建。

3.2 Makefile文件

make命令和Makefike文件是配合使用的,Makefile文件中用来编写任务,任务由依赖关系 + 依赖方法组成

那么什么是依赖关系和依赖方法呢?

比如源文件myfile.c,通过gcc test.c -o myfile命令编译后生成mytfile文件,此时两个文件之间的依赖关系为 myfile:myfile.c ,而依赖方法就是 gcc myfile.c -o myfile

然后将依赖关系和依赖方法写入Makefile文件中

Linux开发工具【gcc/g++】_第16张图片

编写完成后,我们就得到了一个基本的自动化任务,输入 make myfile 就可以直接编译 myfile.c 文件,生成 myfile

Linux开发工具【gcc/g++】_第17张图片

注意:任务刷新策略

  • 同一个自动化任务,执行成功后,如果相关文件最近没有发生改变,那么无法再次执行该任务
  • 想要再次执行任务,需要对源文件做出修改,或者直接 touch 源文件就行了,两种行为都会修改文件的最近修改时间,使源目标文件不是最新时间

Linux开发工具【gcc/g++】_第18张图片

3.3 make指令

直接输入 make 指令时,会默认执行 Makefile 中的第一个自动化任务,当任务成功执行后,不再继续执行后续任务

而使用make 任务名,则可以调用Makefile文件中的任意任务,这里的任务名就是依赖关系中:左侧的名字

Linux开发工具【gcc/g++】_第19张图片

Linux开发工具【gcc/g++】_第20张图片

3.4 .PHONY伪目标

.PHONYMakefile 文件中的一个关键字,用于对某对象生成伪目标,这样可以无视任务刷新策略,重复执行任务

Linux开发工具【gcc/g++】_第21张图片

Linux开发工具【gcc/g++】_第22张图片

.PHONY 关键字,对于源文件编译来说,没什么意义,一般是用来修饰 clean 任务,生成清理任务,实现如下

Linux开发工具【gcc/g++】_第23张图片

Linux开发工具【gcc/g++】_第24张图片

小知识:make 指令的工作原理是去 Makefile 文件中查找任务执行,设计者为了保证适用性,命名为Makefilemakefile都是可以的

4. sudo提权

4.1 sudo使用

当普通用户想去执行某些操作时,会提示权限不够,需要使用root身份,比如一个简单的下载软件操作,就有些麻烦了,为了解决这一情况,可以使用sudo进行提权,也就是暂时借助root的身份去完成某个命令

sudo 命令

当遇到权限拒绝的场景时,只需要使用sudo 命令 ,然后输入密码,就可以暂时root的身份无视权限完成指令了,这里不需要输入root密码,而是输入普通用户的密码,这样可以做到保护root的情况下执行指令

4.2 sudo配置

普通用户默认是没有赋予提权权限的,还是需要切到root用户下进行配置

配置步骤:

  1. 切换到root用户下
  2. 打开/etc/sudoers文件
  3. 翻到最下面,找到指定区域,将需要提权的用户添加进去
//root用户下
vim /etc/sudoers  //进入配置文件,按照下图修改即可

Linux开发工具【gcc/g++】_第25张图片


退出底行模式的时候需要使用wq!指令,这是因为是系统级配置文件所以修改需要慎重,所以必须强制修改


Linux开发工具gcc/g++,到这里就介绍结束了,本篇文章对你由帮助的话,期待大佬们的三连,你们的支持是我最大的动力!

文章有写的不足或是错误的地方,欢迎评论或私信指出,我会在第一时间改正

你可能感兴趣的:(Linux,linux,开发工具,gcc/g++,make/Makefile)