1.Linux编译器-gcc/g++使用
1. 背景知识
接下来的操作,我以gcc为例,因为两者选项都是通用的,所以也就相当于间接学习了
1.预处理(进行宏替换)
2.编译(生成汇编)
3.汇编(生成机器可识别代码)
4.连接(生成可执行文件或库文件)
2. gcc如何完成
格式 :gcc [选项] 要编译的文件 [选项] [目标文件]
2.1预处理(进行宏替换)
预处理功能主要包括宏定义,文件包含,条件编译,去注释等。
预处理指令是以#号开头的代码行。
选项“-E”该选项的作用是:让 gcc 在预处理结束后停止编译过程。
选项“-o” 是指目标文件
“.i”文件为已经过预处理的C原始程序。
我们还可以通过ls来查看gcc中的头文件
2.2编译(生成汇编)
在这个阶段中,gcc 首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作
在检查无误后,gcc 把代码翻译成汇编语言。
用户可以使用“-S”选项来进行查看,该选项只进行编译而不进行汇编,生成汇编代码。
2.3 汇编(生成机器可识别代码)
汇编阶段是把编译阶段生成的“.s”文件转成目标文件
在此可使用选项“-c”就可看到汇编代码已转化为“.o”的二进制目标代码了
2.4连接(生成可执行文件或库文件)
在成功编译之后,就进入了链接阶段。
总结
这里说明一下为什么想要执行程序为什么要在执行文件前加./
简单解释:shell命令执行时的环境变量默认是 $PATH,即到 $PATH 下找命令该如何运行,shell常用的命令在 $PATH 都有,所以可以直接运行。用户新建的文件所在的路径不在 $PATH 下,故直接用文件名来运行是无法运行的,必须加./表示命令就在当前目录下,不要去 $PATH 中找,直接运行就行了。这里再次说明了./表示的是当前目录,而不是执行命令的意思。
3.库
众所周知,每种编程语言都有属于自己的库,比如我们C语言中的 stdio、string、stdlib 等等标准库
当我们程序在调用库函数时,就是在调用标准库中的函数,而这些标准库都在 /usr/include 这个目录中,这个文件就是 Linux 中的C语言动态库;
除了动态库外还有静态库
3.1动态库
动态库即通过动态链接的库,动态库又称共享库
因为动态库中的内容是被所有程序共享的,简言之动态库中的代码只需要存在1份,程序需要使用时,直接通过对应位置调用就行了
Linux 中默认使用动态链接的方式,我们可以通过指令 ldd 最终生成的文件 来查看最终生成文件的链接情况
libXXX.so 是动态链接的标志
其中 lib 是前缀
.so 是后缀
去掉前缀与后缀,就是最终调用的库
举例: libc.so 去掉前缀与后缀,最终为 c,可以看出文件最终调用的是C语言共享库,即动态链接
动态链接 主要依赖不同函数在库中的位置信息进行调用,只有一份代码库,比较节省空间
动态库不能缺失,一旦缺失影响的不止一个程序,影响的是所有有用到这个库的程序
3.2静态库
除了 动态库外,还有静态库
采用静态链接的方式;静态链接不同于动态链接共享的方式
如果程序调用静态库,会将自己所需要的代码拷贝至程序中
完成拷贝后,后续不需要再调用静态库
如果想采用 静态链接 链接的方式编译程序,需要在编译时加上 -static 选项,当然前提是得有静态库,没有的可以通过 yum install -y glibc-static 下载静态库
当然我们也可以通过 ldd 最终生成的文件査看是否为静态链接
静态库 命名为 libXXX.a
lib 是前缀
.a 是后缀
去掉前缀与后缀,就是最终调用的库
因为这种方式很占空间,所以Linux中默认使用动态链接的方式
3.3优劣对比
2.自动化构建工具-makefile
2.1背景
会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力
一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作
makefile带来的好处就是——“自动化编译”
一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令
比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。
可见,makefile都成为了一 种在工程方面的编译方法。
2.2makefile文件
make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建。
要想使用 make 指令,就得先有 Makefile 文件,Makefile 文件中主要编写任务,而任务由依赖关系 + 依赖方法构成
1.依赖关系
比如源文件为 mycode.c,
编译后生成的文件为mycode.exe,那么两者间的依赖关系为 mycode.exe:mycode.c 这组依赖关系 我们可以写入Makefile 文件中
2.依赖方法
有了关系后,就要描述具体实现方法,比如上面那组依赖关系的依赖方法为 gcc mycode -o mycode.exe 将依赖方法也写入Makefile 文件中
2.3make指令
上面展示了如何编写 Makefile 文件并执行相关任务,使用了 makef指令
单纯输入 make 指令时,默认执行 Makefile 中的第一个任务,当任务成功执行后,不再继续执行后续任务(一个makefile 文件中,可以有多个任务)
由此可见,单纯的 make 指令只会执行第一个自动化任务
当我们编写好 Makefile 文件后,可以通过 make任务名调用任务
任务名就是依赖关系中的左侧名
也可以直接通过 make 调用第一个任务
make指令可以自动有序生成文件
2.3任务刷新策略
同一个方法如果成功执行过,在原文件最近修改时间没有发生变化时,无法再执行任务
这背后的原因是方法是否执行会先判断生成的目标文件是否为最新,如果为最新,就不再执任务
2.4.PHONY伪目标
.PHONY 是 Makefile 文件中的一个关键字,意为对某某对象生成伪目标,这样就能在不对源文件进行修改的情况下,重复执行任务了
注意:
像 clean: 这种半缺失依赖方法是合理的,毕竟清理这个任务也不需要任何对象,只需要单纯的执行删除(清理)指令就行了
2.5补充
3.添加用户白名单
权限,是一个让人又爱又恨的东西,它的安全性固然很重要,但有时候又太麻烦了,当我们普通用户想执行操作时,比如最基本的下载软件指令,需要请root
Linux 中就有 sudo 提权 这个概念,简单来说,就是暂时借助 root 的身份去完成某条指令
使用sudo的时候只需要输入自己用户的密码,无需输入root用户的密码
但是sudo指令的执行要进入root的白名单才可使用
添加用户白名单只需要先用root账户进入一个配置文件
注意:退出文件的时候要用:wq!
进行强制性保存退出