在Linux下安装软件,在很久的以前,是通过下载到程序的源代码,然后编译得到可执行程序,但是这样做太麻烦了,所以在以后的时间里,就有人将一些常用的软件提前编译好,做成软件包(类似手机上的软件),放在服务器上,通过软件包管理器(类似手机上的应用商店)我们可以很容易的找到这个软件包,然后将它下载安装,yum就是Linux下常用的一种包管理器
我们可以通过指令来查看我们当前的yum源是哪一个,由图可知,我们的yum源是华为源,当然我们这里用的是华为的云服务器
这里使用的是云服务器,有些用户用的是虚拟机进行开发,yum源有点老了,我们就可以将yum源进行更换,就把这个文件CentOS-Base.repo换成我们新的yum就可以了,其实是改变里面获取yum的网址,但是我们不建议大家打开文件修改网址,直接拿一个现成的文件替换掉就可以了
如果主机上没有yum,可以通过以下命令来下载“应用商店”
yum install -y epel-release
yum install … (安装软件 yum remove …(卸载软件
先在目录下创建一个makefile文件
然后用vim打开,先写明依赖关系,如下图所示,test依赖于test.o,意思就是说test没有test.o是无法生成的,test.o依赖于test.s,test.s依赖于test.i,test.i依赖于test.c,clean不依赖任何文件,然后在依赖关系的下一行table然后写明为什么依赖,也就是后面生成前面所需要的指令
当我们写好makefile文件后,直接输入make指令就可以把我们在makefile中实现的一键实现
当我们make clean一下,以iso为后缀的文件都被清理了
以刚才的例子举例,当我们输入make指令时,make指令会在当前目录下寻找makefile/Makefile文件(开头大小写都可以,功能一样的),如果找到,它会找到文件中第一个目标文件test,并把这个文件作为最终的目标文件,然后test依赖的是test.o,test.o文件不存在我们就找test.o文件,然后发现test.o文件依赖test.s文件,以此类推,最终找到test.c文件然后往回推,产生.i.s.o文件,最终编译出目标文件test,如果在编译的过程中遇到错误,那么会直接退出并报错
当然我们平常不需要中间文件的时直接如下图所示就可以了
当我们构建项目的时候,工程文件是需要清理的,clean就起到一个清理的作用,它不依赖任何文件,所以它:后面没有别的东西,然后指令为rm,我们通过make clean来进行工程文件的清理
我们发现,clean我们需要make clean来实现,test只需要make就可以了,当我们将make test指令输入后得到的是和make一样的结果,所以,make后面不带任何东西默认进行构建目标文件的操作,但也可以将目标文件输入像make test一样,效果是一样的,除了目标文件以外的所有类似clean的都要make clean才能执行
并且make有一个保护效果,那就是在修改文件之前,禁止多次编译,也就是说make只能来一下,来一下之后你就要修改过源文件才能继续make,时间的比较机制是这样的:通过将时间转化为时间戳比较生成目标文件的时间戳与源文件时间戳的大小,如果目标文件的时间戳更大,就不能make,如果源文件的时间戳更大,就可以make
如果我们想要不顾上述这个保护效果,想要多次编译我们可以通过伪目标的机制来进行,它可以使被选中的行为总是可执行,就是在上面一行加一个 .PHONY:源文件
但我们一般还是使用这个保护机制的,因为这个保护机制是非常有用的,可以防止我们多次编译造成不必要的资源浪费,所以我们一般在写makefile文件的时候都是把.PHONY加到make clean的前面的
原因如下: 第一,避免与文件冲突,通常,make clean 被用来删除一些在构建过程中生成的文件,比如 .o 目标文件、可执行文件和其他临时文件,它的目的是将项目恢复到一个干净的状态,以便进行新的构建或者进行其他操作,如果 clean 不是一个伪目标,而项目中存在一个名为 clean 的文件,那么 make 工具会根据文件的时间戳来判断是否需要执行该目标的命令,如果 clean 文件比其依赖文件更新,make 将认为该目标是最新的,从而不会执行 make clean 的命令,这就违背了 make clean 的初衷
第二,明确执行操作的意图,当将 clean 定义为伪目标时,它明确地告诉 make 工具,clean 是一个不对应任何文件的目标,make 应该总是执行其命令,而不考虑文件的存在和时间戳
第三,保持makefile的一致性和可维护性,使用伪目标可以让 makefile 的行为更加可预测,对于像 clean 这样的目标,我们通常希望它执行一个操作而不是构建一个文件,将其定义为伪目标符合其操作的性质,使 makefile 的逻辑更加清晰
上面两份代码意义相同
符号 | 意义 |
---|---|
$@ | 表示规则中的目标文件 |
$^ | 表示规则中的所有依赖文件 |
$< | 表示规则中的第一个依赖文件 |
我们在初始学习C语言的时候,如果不是在学校中学的,一般我们用的第一个编译器是VS或者VScode,以VS为例,在学习过程中我们会学到一个能力叫做调试,调试成立的条件是建立在程序是以debug方式发布的
我们都知道程序的发布方式有两种,一种叫做debug,另一种叫做release,在Linux中通过gcc和g++编译出的程序默认是release版本的,如果我们要对代码进行调试,就需要debug版本,就要在源代码生成二进制程序的时候加上-g选项,而在Linux中进行调试的调试工具就是gdb
创建一个我们开始学习C语言调试时候的简单例子,加法程序
test是通过debug版本发行的,test_r是release版本发行的,可以明显看出debug版本发行的test文件更大
gdb [文件名]
通过指令开始进入调试
命令 | 缩写 | 描述 |
---|---|---|
break <行号> | b <行号> | 在程序的指定行号处设置断点 |
break <函数名> | b <函数名> | 在指定的函数入口处设置断点 |
info breakpoints | i b | 显示当前设置的所有断点信息 |
run | r | 开始运行程序,如果程序需要命令行参数可在其后添加 |
next | n | 执行下一行代码,但不进入函数内部,函数调用会直接执行完 |
step | s | 执行下一行代码,若为函数调用则进入函数内部 |
print <变量名> | p <变量名> | 打印变量的值 |
display <表达式> | 跟踪显示,每次程序暂停时都显示该表达式的值 | |
undisplay<表达式> | 取消跟踪 | |
backtrace | bt | 显示当前的调用栈信息 |
continue | c | 从当前位置继续执行程序,直到下一个断点或程序结束 |
clear <行号> | cl <行号> | 清除指定行号的断点 |
delete <断点编号> | d <断点编号> | 删除指定编号的断点 |
quit | q | 退出 GDB 调试会话 |
break <行号> if <条件> | b <行号> if <条件> | 在满足特定条件时触发断点 |
watch <表达式> | 当表达式的值发生变化时,程序会暂停 | |
info threads | 显示所有线程的信息 | |
thread <线程编号> | 切换到指定的线程进行调试 | |
list <行号> | l <行号> | 列出以行号为中心的上下共10行代码 |
list <函数名> | l <函数名> | 列出某个函数的源代码 |
finish | 执行到当前函数返回,然后停下来等待命令 |
gdb和VS的对应表格就在上边,对应起来的效果与VS效果是相同的
大家还是尽量养成使用调试工具的习惯,这样找bug还比较规范,不会遇到痛苦的地方~
今日分享就到这里了~