Linux工具:make/Makefile 自动化构建、Git 版本控制器 和 gdb/cgdb 调试器
- make/Makefile 自动化构建
- 在 Linux 命令行中的命令 make
- Makefile 的基本操作
- 1. 编写与删文件基本操作
- 2. 总是执行操作
- 3. 执行操作时的依赖性
- 4. 定义变量或命令操作与其它简单操作
- 5. 多文件操作
- Git 版本控制器
- Git 简单使用
- 忽略文件
- 在 Linux 命令行中的命令 git
- 克隆远程仓库到本地命令 git clone
- 配置参数信息命令 git config
- 添加新文件或目录到本地暂存区命令 git add
- 重置命令 git reset
- 将暂存区内容添加到本地仓库命令 git commit
- 将本地仓库内容推送到远程仓库命令 git push
- 将远程仓库内容覆盖到本地仓库命令 git pull
- 查看仓库历史提交信息命令 git log
- 查看暂存区内容命令 git status
- gdb/cgdb 调试器
- 在 Linux 命令行中的命令 gdb/cgdb
- gbd 的基本命令
- 设置断点命令 b/break
- 删除断点命令 d/delete
- 运行程序命令 r/run
- 单步逐过程执行命令 n/next
- 单步逐语句执行命令 s/step
- 继续执行命令 c/continue
- 查看变量或表达式值命令 p/print
- 显示源代码命令 l/list
- 查看当前执行栈的信息命令 bt/backtrace
- 查看指定信息命令 i/info
- 查看执行位置的函数与行号 f/frame
- 退出 gdb 命令 q/quit
- 监视变量或表达式值命令 display
- 取消监视命令 undisplay
- 执行到指定行号命令 until
- 禁用断点命令 disable
- 启用断点命令 enable
- 执行到函数返回命令 finish
- gdb 的其它命令
- 修改运行时的变量值命令 set var
- 监视变量或表达式是否变化命令 watch
- 添加条件断点命令
- 给已有断点设置条件判断命令 condition
- gdb 常用快捷键
- cgdb 与其界面操作
make/Makefile 自动化构建
一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,Makefile 定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作。 Makefile 带来的好处就是 ⸺ “自动化编译”,一旦写好,只需要一个 make 命令,整个工程完全自动编译,极大的提高了软件开发的效率。
make 是一个命令工具,是一个解释 Makefile 中指令的命令工具,一般来说,大多数的 IDE 都有这个命令,比如:Delphi 的 make,Visual C++ 的 nmake,Linux 下 GNU 的 make。可见,Makefile 都成为了一种在工程方面的编译方法。
make 是一条命令,Makefile 是一个文件,两个搭配使用,完成项目自动化构建。
在 Linux 命令行中的命令 make
语法:make [选项] [目标]
功能:执行 Makefile 文件中的目标
常用选项:
- -f [文件名] :指定使用的 Makefile 文件名。默认情况下,make 会在当前目录下查找名为 Makefile 或 makefile 的文件
- -n :只打印要执行的命令,但不实际执行
- -s :安静模式,不显示执行的命令,只显示执行结果
- -B :强制重新构建所有目标
- -C [目录路径] :切换到指定目录后执行 make
- -k 出错时继续执行其他目标
- -j [并行任务数] :指定并行执行的任务数,加快编译速度
其它操作:
- 不指定文件名,make 默认会在当前目录搜索并使用名为
Makefile
或makefile
的文件。
对于目标,输入目标后 make 命令会进入 Makefile 文件中寻找目标,然后执行目标。如果不输入,默认寻找 Makefile 文件中从上到下的第一个目标。
Makefile 的基本操作
1. 编写与删文件基本操作
Makefile 文件编写的一个基本规则,规则格式如下:
[目标]:[目标依赖的文件或目标] # 依赖关系
在目标下执行的命令 # 命令部分必须以 Tab 开头,表示依赖的方法
例如我们需要编写一个文件和删除它,可以这样写:
test.exe:test.c
gcc test.c -o test.exe
#...其它命令
clean:
rm -f test.exe
- 当执行 test.exe 目标时,会去执行命令
gcc test.c -o test.exe
将 test.c 编译成可执行文件 test.exe 然后结束 - 当执行 clean 目标时,会执行命令
rm -f test.exe
将 test.exe 可执行文件删掉
2. 总是执行操作
对于编译文件操作,执行编译完成后不修改就不允许再次执行,如果想要一直可执行,可添加关键字 .PHONY:[目标]
:
.PHONY:test.exe # 表示 test.exe 可以一直执行
test.exe:test.c
gcc test.c -o test.exe
#...其它命令
clean:
rm -f test.exe
这是因为 Makefile 会检查编译文件是否被重复执行,根据编译生成的文件与源代码文件的 Modify(修改时间) 来对比的:
没有 .PHONY:test.exe
时,Makefile 通过对比 Modify 就可以阻止未修改的源文件再次被编译,减少无用的编译行为:
3. 执行操作时的依赖性
Makefile 的依赖性依靠栈结构处理:
Makefile 执行 test.exe
目标时,发现它依赖另一个目标 test.o
,而 test.o
又依赖 test.s
…直到可以执行的目标 test.i
时才会开始执行其中的命令。在此之前依赖关系的命令会存储到一个栈结构中,当依赖的目标命令执行后会出栈,此时栈顶就是上一个命令,出栈执行,直到栈空为止:
在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么 make 就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make 不会处理。
4. 定义变量或命令操作与其它简单操作
为方便替换文件或命令操作,Makefile 中允许定义变量或命令,可以认为与C语言宏定义差不多:
-
定义操作可方便更改,当要使用定义的变量或命令时,
$(变量或命令)
即使用 $ 符号且用圆括号括起来就可以正常引用。 -
在目标下的命令操作中,可以用
$@
代表目标,用$^
代表目标依赖的文件或目标。 -
在目标下的命令前加上符号
@
表示当前的命令不会打印在屏幕上。 -
Makefile 文件中可用
#
注释当前行
5. 多文件操作
Makefile 可以使用 %
通配符匹配当前目路的特定文件,在目标下的命令中用 <
表示每个特定的文件,也可以认为用法与 ^
相同:
当然,在 Makefile 中手写需要编译的源文件太过浪费时间。
- 可以在 Makefile 中执行 shell 命令寻找文件或者使用 Makefile 内提供的 wildcard 函数
$(wildcar [文件名1] [文件名2]...)
搜索文件名 - 再使用 Makefile 的后缀替换语法
$(变量:.旧文件后缀=.新文件后缀)
成批量的替换后缀名即可
Git__98">Git 版本控制器
为了能够方便我们管理不同版本的文件,便有了版本控制器。所谓的版本控制器,就是能让我们了解到一个文件的历史,以及它的发展过程的系统,通俗的讲就是一个可以记录工程的每一次改动和版本迭代的一个管理系统,同时也方便多人协同作业。
目前最主流的版本控制器就是 Git 。Git 可以控制电脑上所有格式的文件,例如 doc、excel、dwg、dgn、rvt 等等。对于我们开发人员来说,Git 最重要的就是可以帮助我们管理软件开发项目中的源代码文件。
Git 的特点:
- 速度
- 简单的设计
- 对非线性开发模式的强力支持(允许成千上万个并行开发的分支)
- 完全分布式
- 有能力高效管理类似 Linux 内核一样的超大规模项目(速度和数据量)
Git__110">Git 简单使用
如果想要简单的使用 Git 管理源代码版本,只需几个步骤:
- 使用 git clone 命令将远程仓库克隆到本地
- 使用 git config 命令配置 user.name 和 user.email 信息
- 编写代码后在当前仓库工作目录使用 git add 命令将文件提交到暂存区中
- 使用 git commit 命令将暂存区中文件提交到本地仓库并描述本次提交信息
- 使用 git push 命令将本地仓库内容推送到远程仓库中
- 若绕过自己本地仓库直接修改远程仓库,使用 git pull 命令同步本地与远程仓库
忽略文件
.gitignore 文件可以忽略特定后缀的文件,一般需要存放在 Git 仓库同一个目录下,在 git add
命令添加文件时会自动过滤不需要的文件:
在 .gitignore 文件中可以自定义的编辑不想要的文件:
在 Linux 命令行中的命令 git
克隆远程仓库到本地命令 git clone
语法:git clone [选项] [远程仓库地址] [本地目录名]
功能:将远程仓库的内容完整地复制到本地,包含所有分支历史、标签和配置,克隆后会自动创建与远程仓库的关联(origin 别名)
常用选项:
--depth=[n]
:用于进行浅克隆,只克隆最近 n 次的提交历史,而不是完整的提交历史-b [分支名]
或--branch [分支名]
:指定要克隆的远程分支,而不是默认的分支- --quiet :仅显示错误信息
- --recursive :递归克隆子模块
其它操作:
- 本地目录名不填默认在当前目录进行克隆
配置参数信息命令 git config
语法:git config [选项] [配置项]
功能:配置各种参数的命令,如系统级配置、全局配置、仓库级配置等,以满足不同的使用需求
常用选项:
- --system :表示对系统中所有用户的所有仓库都生效的系统级配置
- --global :表示对当前用户的所有仓库生效的全局配置
- --local :表示仅对当前所在仓库生效的配置
- --list :查看指定级别的配置信息
- --unset :表示删除指定的配置信息
- --get :获取指定配置项的内容
--get-all
:获取指定配置项的所有内容--replace-all
:替换指定配置项的所有现有内容为新的内容- --add :为指定的配置项添加一个新的内容,而不是替换原有的内容
- --edit :打开相应级别的配置文件,让用户直接编辑配置内容
--get-regexp
:根据正则表达式匹配配置项的名称,并列出匹配的配置项及其值
常用配置项:
user.name "名称"
:表示配置指定作者名称user.email "邮箱"
:表示配置指定的邮箱core.editor "编辑器"
:表示配置指定的文本编辑器alias.st "已有命令"
:表示对命令取一个别名
添加新文件或目录到本地暂存区命令 git add
语法:git add [文件或目录]
功能:将文件或目录存入本地仓库的暂存区里,方便选择取消或推送。
其它操作:
git add .
表示添加当前目录下所有修改和新增的文件(不包括删除的文件)
重置命令 git reset
语法:git reset [选项] [提交引用] [文件路径]
功能:可以撤销提交、移除暂存区的文件或者恢复工作目录中的文件
常用选项:
- --soft :仅移动 HEAD 指针到指定的提交,暂存区和工作目录的内容保持不变,即当前提交内容被撤销,回退到上一个提交
- --mixed :移动 HEAD 指针到指定的提交,同时重置暂存区,使其和指定提交的内容一致,但工作目录中的文件内容保持不变,即之前提交的修改会从暂存区移除
- --hard :移动 HEAD 指针到指定的提交,同时重置暂存区和工作目录,保持两者与指定提交的内容一致,即之前的提交被撤销,并且工作目录中未提交的修改也会被彻底丢弃,无法恢复(谨慎使用)
将暂存区内容添加到本地仓库命令 git commit
语法:git commit [选项]
功能:将文件或目录更新到本地仓库中。
常用选项:
-m [描述信息]
:提交暂存区的所有更改,并附加简短的描述消息- --amend : 修改最后一次提交,可用于修复提交的描述信息的拼写错误和将漏掉的文件添加到上次提交(先用 git add 添加文件,再运行此命令)
- -a :自动将所有已跟踪文件(即已被 Git 管理的文件)的修改添加到暂存区,并进行提交,可以认为相当于先执行
git add
再执行git commit
操作。
其它操作:
git commit
不提供 -m 参数,Git 打开默认文本编辑器(如 Vim 或 Nano),允许编写多行提交消息。
将本地仓库内容推送到远程仓库命令 git push
语法:git push [选项] [远程仓库名] [本地分支名]:[远程分支名]
功能:将本地仓库内容推送到远程仓库。
常用选项:
- -f 或 --force :无视本地分支和远程分支的历史记录不一致,强制推送。(可能会导致其他人的提交丢失,需谨慎使用)
- --all :将本地的所有分支推送到远程仓库
- --tags :推送本地的所有标签到远程仓库
- --delete :指定删除远程分支名
其它参数说明:
- 远程仓库名:一般默认的远程仓库名为 origin,它是在使用 git clone 克隆远程仓库时自动创建的指向该远程仓库的引用。
- 本地分支名:指的是需要推送的本地分支的名称
- 远程分支名:即希望将本地分支的提交推送到远程仓库的哪个分支
其它操作:
git push
:表示将当前本地仓库更新的分支自动提交到默认的远程仓库(一般需要填写远程仓库所在账号的账号与密码)
将远程仓库内容覆盖到本地仓库命令 git pull
语法:git pull [选项] [远程仓库名] [远程分支名]:[本地分支名]
功能:将远程仓库内容覆盖到本地仓库。
常用选项:
- --force :强制覆盖本地修改(谨慎使用)
- --rebase :避免生成多余的合并提交,保持提交历史线性(适用于协作开发场景)
其它操作:
git pull
:表示将默认的远程仓库内容覆盖到本地仓库。
查看仓库历史提交信息命令 git log
语法:git log [选项]
功能:查看仓库项目的提交历史记录
常用选项:
- 没有选项可以显示最近到最远的提交历史记录
- --oneline :将每个提交记录压缩为一行显示,只显示提交哈希的前几位和提交信息
- -[n] :限制显示的提交记录数量,n 为具体的数字
- --graph :以图形化的方式显示提交历史,清晰展示分支的合并情况
--author=[作者名]
:显示指定作者的提交记录--since="开始日期" --until="结束日期"
:显示该范围内的提交记录--grep="关键字"
:显示包含 关键字 的提交记录--pretty=format:"格式"
:自定义提交记录的输出格式,常用符号:- %h :表示缩写的提交哈希
- %an :表示作者名
- %ar :表示相对日期
- %s :表示提交信息
查看暂存区内容命令 git status
语法:git status [选项]
功能:查看当前工作目录和暂存区中文件的状态
常用选项:
- -s 或 --short :以简短的格式显示文件状态
- -b 或 --branch :显示当前分支的信息,包括分支名称、与远程分支的对比情况(如是否领先、落后等)
- --ignored :显示那些被
.gitignore
文件忽略的文件
gdb/cgdb 调试器
程序的发布方式有两种, debug 模式和 release 模式, Linux gcc/g++ 编译出来的二进制程序,默认是 release 模式。
要使用 gdb 命令行调试工具调试程序,必须在源代码使用 gcc/g++ 生成二进制程序的时候,,加上 -g 选项,如果没有添加,程序无法被 gdb 调试。
其中,cgdb 是在 gdb 基础之上的一个文本界面的图形化调试器,它结合了 gdb 的调试功能与类似 vim 的界面查看源代码,调试时能更直观:
在 Linux 命令行中的命令 gdb/cgdb
语法:
gdb [可执行文件]
cgdb [可执行文件]
功能:调试程序,查找 bug
gbd 的基本命令
设置断点命令 b/break
语法:
b [行号或函数名]
break [行号或函数名]
功能:设置断点,用于调试
删除断点命令 d/delete
语法:
d [断点编号]
delete [断点编号]
功能:删除对应编号的断点
其它操作:
d 或 delete
:不带编号会将所有断点删除
运行程序命令 r/run
语法:
r
run
功能:开始运行程序
单步逐过程执行命令 n/next
语法:
n
next
功能:单步执行下一行代码,但不进入函数内部
单步逐语句执行命令 s/step
语法:
s
step
功能:单步执行下一行代码,如果是函数调用,会进入函数内部
继续执行命令 c/continue
语法:
c
continue
功能:继续执行程序,直到到达下一个断点或程序结束
查看变量或表达式值命令 p/print
语法:
p [变量或表达式]
print [变量或表达式]
功能:打印变量或表达式的值
显示源代码命令 l/list
语法:
l [选项]
list [选项]
功能:在 gdb 命令行中显示源代码
常用选项:
[行号]
:显示当前行号为中心的一部分源代码[函数名]
:列出指定函数的源代码[文件名:行号]
:列出指定文件对应行号为中心的一部分源代码
查看当前执行栈的信息命令 bt/backtrace
语法:
bt
backtrace
功能:查看当前执行栈的各级函数调用、参数与执行的对应行号
查看指定信息命令 i/info
语法:
i [选项]
info [选项]
功能:查看其它命令的信息
常用选项:
[b/break]
:查看当前所有断点的信息[locals]
:查看当前栈帧的局部变量值
查看执行位置的函数与行号 f/frame
语法:
f
frame
功能:查看当前程序执行到的函数信息与行号
退出 gdb 命令 q/quit
语法:
q
quit
功能:退出 gdb
监视变量或表达式值命令 display
语法:
display [变量或表达式]
功能:监视变量或表达式的值,当程序进行下一步操作,会自动打印
取消监视命令 undisplay
语法:
undisplay [监视编号]
功能:取消对应编号的监视
其它操作:
undisplay
:不打印监视编号时会取消所有监视
执行到指定行号命令 until
语法:
until [行号]
功能:将程序执行到指定行号
禁用断点命令 disable
语法:
disable [断点编号]
功能:禁用特定断点
其它操作:
- 不写断点编号表示禁用所有断点
启用断点命令 enable
语法:
enable [断点编号]
功能:启用特定断点
其它操作:
- 不写断点编号表示启用所有断点
执行到函数返回命令 finish
语法:
finish
功能:执行到当前函数返回,然后停止
gdb 的其它命令
修改运行时的变量值命令 set var
语法:set var [变量名]=[值]
功能:在程序运行时修改变量具体的数值
监视变量或表达式是否变化命令 watch
语法:watch [变量或表达式]
功能:监视变量或表达式是否发生变化,如果发生变化,停止程序并打印对比变化前与变化后的值。其等价于一个条件断点,可以删除它
添加条件断点命令
语法:
b [选项] if [变量或表达式] == [变量或表达式]
break [选项] if [变量或表达式] == [变量或表达式]
功能:在原来的断点命令上增加条件判断,若条件不满足,则不会在此断点停下
给已有断点设置条件判断命令 condition
语法:condition [断点编号] [变量或表达式] == [变量或表达式]
功能:对已有的断点设置一个条件判断,若条件不满足,则不会在此断点停下
gdb 常用快捷键
gdb 常用快捷键:
- 只按回车键会执行上一次历史命令
- 使用上下键可以翻阅历史命令
Ctrl+L
刷新屏幕
cgdb 与其界面操作
cgdb 在 gdb 的基础上提供了一个分屏界面(上方显示源码,下方是 gdb 命令行),不仅保留 gdb 命令行的使用,还在界面上支持代码高亮、快捷键操作和更直观的调试体验。
在 cgdb 处于 gdb 命令行中,使用 Esc 按键进入界面操作,使用 i 按键可以从界面返回 gdb 命令行操作。
注意,cgdb 界面快捷键在不同版本中可能会不同,以下快捷键仅供参考。
cgdb 常用界面快捷键操作:
- 上下或 h、k 键移动光标:使用上下键或者 h 键(下移) 和 k 键(上移) 可以移动光标。
- 空格键可在光标处设置断点或取消断点
/[关键字]
:在光标当前行向下搜索关键字,若找到并回车光标会移动到所在行号?[关键字]
:在光标当前行向上搜索关键字,若找到并回车光标会移动到所在行号:[行号]
:回车确定后光标跳转到指定行号- F5 按键与 gdb 命令行的 运行程序命令 r/run 相同
- F6 按键与 gdb 命令行的 继续执行命令 c/continue 相同
- F7 按键与 gdb 命令行的 执行到函数返回命令 finish 相同
- F8 按键与 gdb 命令行的 单步逐过程执行命令 n/next 相同
- F10 按键与 gdb 命令行的 单步逐语句执行命令 s/step 相同