Linux常见工具使用

2025博客之星年度评选已开启 10w+人浏览 1.2k人参与


个人主页

🎬 个人主页Vect个人主页

🎬 GitHubVect的代码仓库

🔥 个人专栏: 《数据结构与算法》《C++学习之旅》《Linux

⛺️Per aspera ad astra.


Makefile

0. 简单代码演示

// add.h
#pragma once 

int add(int a, int b);
// add.cpp

#include "add.h"

int add(int a, int b) { return a + b;}
// main.cpp

#include <iostream>
#include "add.h"

int main(){
    std::cout<<add(1,2)<<std::endl;
    return 0;
}

1. Makefile结构及规则

这里先提前有个认知:

  • Makefile是文件
  • make是指令

先来看代码,然后解读:

# 变量定义部分
SRC = main.cpp add.cpp 
OBJ = $(SRC:.cpp=.o)
BIN = myapp

# 默认目标
$(BIN): $(OBJ)
	g++ -o $@ $^
	
# 编译目标
%.o: %.cpp
	g++ -c $< -o $@
	
# 清理目标
.PHONY: clean
clean:
	rm -f $(OBJ) $(BIN)
	

变量定义部分

SRC = main.cpp add.cpp

  • 作用:定义源文件变量,包含所有.cpp的源文件
  • 解释:SRC是一个包含需要编译的源文件的列表

OBJ = $(SRC:.cpp=.o)

  • 作用:通过模式替换,将SRC中的.cpp全部转换成.o文件
  • 解释:$(VAR)用来引用一个变量的值,$(SRC:.cpp=.o)利用替换模式得到OBJ = main.o add.o

BIN = myapp

  • 作用:定义最终生成的目标文件名(最后的可执行文件)

默认目标部分

$(BIN):$(OBJ)

  • 作用:表示目标$(BIN) 依赖于$(OBJ)中的main.o add.o

g++ -o $@ $^

  • 作用:使用g++.o文件链接成最终可执行文件myapp
  • 解释:
    • $@:代表当前规则中的目标文件,这里是$(BIN)
    • $^:代表所有的依赖文件(去除重复的),这里是$(OBJ)

编译目标部分

%.o: %.cpp

  • 作用:表示一条通用规则,告诉make如何将.cpp文件编译成.o文件
  • 解释:%是通配符,代表一个任意的字符序列,这里表示会匹配所有的.cpp文件,将它们全部编译为对应的.o文件

g++ -c &< -o $@

  • 作用:使用g++.cpp文件编译成.o文件
  • 解释:
    • $<:代表当前规则中的第一个依赖文件,在这里就是 .cpp 文件
    • $@:表示当前规则中的目标文件,在这里是 .o 文件

清理目标部分

.PHONY: clean

  • 作用:声明clean是一个伪目标,而不是文件名
  • 解释:make 会认为 clean 是一个任务,而不是文件,因此即使当前目录下存在名为 clean 的文件,make 也会执行 clean 规则的命令

clean: rm -f $(OBJ) $(BIN)

  • 作用:clean 目标的命令部分,删除所有生成的目标文件和最终的可执行文件。

2. 过程推导

目标文件.o和依赖关系

  • main.o依赖于main.cpp
  • add.o依赖于add.cpp

在Makefile中,$OBJ 是要生成的目标文件,它的生成依赖于.cpp文件

规则推导过程

make会从默认目标myapp开始,通过依赖关系逐步推导出需要做的工作

  1. make看到myapp

    myapp的形成依赖于main.oadd.omake会从main.oadd.o开始推导

  2. 生成main.o

    main.o的生成又依赖于main.cpp,所以make会执行:g++ -c main.cpp -o main.o

  3. 生成add.o

    同理add.o的生成依赖于add.cpp,所以make会执行: g++ -c add.cpp -o add.o

  4. 链接成myapp

    当生成了main.oadd.omake会执行:g++ -o mayapp main.o add.o

推导是一个出栈入栈的过程

  • 出栈:make开始时看到myapp,出栈myapp,处理它的依赖main.oadd.o
  • **入栈:**当 main.oadd.o 处理完后,它们的目标文件会 入栈,然后 make 执行生成 myapp 的命令

我们梳理清楚依赖链:

目标直接依赖构建规则
myappmain.o add.og++ -o myapp main.o add.o
main.omain.cppg++ -c main.cpp -o main.o
add.oadd.cppg++ -c add.cpp -o add.o
clean伪目标rm -f main.o add.o myapp

image-20251214205218108

时间戳

make在做依赖关系推导的时候,会用时间戳来决定哪些目标需要重新构建

时间戳的作用

make会比较每个目标文件和它的依赖文件的时间戳

  • 如果依赖文件比目标文件新,make会重新构建目标文件
  • 如果目标文件存在且没有被更新,make会跳过编译过程
[vect@VM-0-11-centos make_file]$ stat main.cpp
  File: ‘main.cpp’
  Size: 102       	Blocks: 8          IO Block: 4096   regular file
Device: fd01h/64769d	Inode: 1051720     Links: 1
Access: (0664/-rw-rw-r--)  Uid: ( 1002/    vect)   Gid: ( 1002/    vect)
Access: 2025-12-14 20:12:03.883557588 +0800
Modify: 2025-12-14 20:12:01.955499062 +0800
Change: 2025-12-14 20:12:01.955499062 +0800
 Birth: -

看一下三种时间:

  • Acesstime:访问时间,文件内容被读取/访问的时间
  • Modifytime:修改时间,文件时间内容被修改的时间(文件大小、内容变化)
  • Changetime:状态改变时间,文件**元数据(属性)**改变的时间(文件属性)

过程演示:

  1. 第一次运行make

    make的行为:

    [vect@VM-0-11-centos make_file]$ make
    g++ -c main.cpp -o main.o
    g++ -c add.cpp -o add.o
    g++ -o myapp main.o add.o
    

    此时目标文件和可执行文件都生成了,时间戳被记录

  2. 修改源文件并运行make

    假设修改了 add.cpp 文件中的代码,例如:

    int add(int a, int b) {
        return a * b;  // 修改了加法为乘法
    }
    

    现在,make会根据文件时间戳决定是否重新编译:

    • main.o时间戳未变化,main.cpp不重新编译
    • add.o文件的时间戳比add.cpp新,make会发现add.o的依赖文件add.cpp发生变化

    运行指令得到:

    [vect@VM-0-11-centos make_file]$ make
    g++ -c add.cpp -o add.o
    g++ -o myapp main.o add.o
    
  3. 不做任何修改,直接运行make

    [vect@VM-0-11-centos make_file]$ make
    make: `myapp' is up to date.
    

总结:

  1. 目标文件不存在:如果目标文件(.o)或依赖文件(.cpp)不存在,make 会强制编译并生成目标文件。

  2. 依赖文件更新:如果依赖文件的时间戳比目标文件更新,make 会重新编译依赖文件并更新目标文件。

  3. 无更新时跳过编译:如果目标文件和依赖文件的时间戳都没有变化,make 会跳过编译过程,避免重复工作。

image-20251214211248458

伪目标

伪目标:没有对应文件的目标文件,用来执行命令而不关心文件的存在

伪目标不会检查时间戳,每次执行都会运行相关指令

.PHONY: clean

clean:
    rm -f $(OBJ) $(BIN)

.PHONY 告诉 make clean 是伪目标,即使当前目录下有一个 clean 文件,make 也不会认为它是一个文件,而是会执行 rm 命令

gdb调试

gdb使用须知

程序发布方式:

  1. debug版本:程序本身会被加入更多调试信息,便于调试
  2. release版本:不添加任何调试信息,不可调试

在Linux下,gcc/g++默认生成的可执行程序是release版本,若想生成debug版本,就需要加上-g选项

image-20251217212752259

对同一代码分贝生成release版本和debug版本的可执行程序,可以看到debug版本要更大,原因是debug版本包含了更多的调试信息

gdb命令汇总

【进入gdb】

gdb 二进制文件名

【退出】

ctrl+dquit调试命令

【常见命令】

  • list/l:列出源代码,从上次位置开始,每次列10行

  • list/l 函数名:列出指定函数的源代码

  • list/l 文件名:行号:列出指定文件的源代码

  • run/r:从程序开始连续执行

    image-20251217214004458

  • next/n:单步执行,不进入函数内部,相当于逐过程F10

  • step/s:单步执行,进入函数内部,相当于逐语句F11

  • break/b 文件名:行号:指定行号打断点,b 10 b test.c:10

  • info break/b:查看当前所有断点信息

    image-20251217214424216

    这里显示断点编号和断点类型以及其他信息

  • finish:执行到当前函数返回,然后停止

  • print/p 表达式:打印表达式的值

  • p 变量:打印指定变量的值

  • set var 变量=值:修改变量的值

  • continue/c:从当前位置开始连续执行程序

  • delete/d breakpoints:删除所有断点

  • delete/d breakpoints n:删除序号为n的断点

  • disable breakpoints:禁用所有断点

  • enable breakpoints: 启用所有断点

  • info/i breakpoints:查看当前设置的断点列表

  • display 变量名:跟踪显示指定变量的值

  • undisplay 编号:取消对指定编号的变量的跟踪显示

  • until x:执行到指定行号

  • backtrace/bc:查看当前执行栈的各级函数调用及参数

  • info/i locals:查看当前栈帧的局部变量值

vim的使用

vim是一种多模式编辑器,总共有12种模式,本文只详细讲解三种常见模式:命令模式 插入模式 第行模式

  • **命令模式:**控制光标的移动,进行字符或行的删除,移动复制某区域内容
  • **插入模式:**文本编辑
  • 底行模式: 文本保存、退出、文件替换、查找文本内容、执行命令
  • 替换模式: 文本替换
  • 视图模式:

1. 命令模式操作

  • 进入vim

    vim file,如果文件不存在就会自动创建并进入vim编辑器页面,默认进入命令模式

  • 命令模式->插入模式

    输入a:光标后移一位进入编辑

    输入o:光标另起一行到行首进入编辑

    输入i:光标位置进入编辑

  • 命令模式->底行模式

    shift+; 就是输入:

  • 退出vim并保存文件: 从命令模式转到底行模式

    w:保存当前文件

    wq:保存并退出

    q!:不保存强制退出

  • 复制 注意:n代表数字

    n+yy:光标所在行开始,复制n行

    n+p:从光标所在行下一行行首开始,粘贴n次

    u:撤销上一次操作

    ctrl+r:取消撤销

  • 移动光标

    shift+g:即G,定位到文本末尾

    gg:定位到文本开头

    n+shift+g:定位到第n行

    h j k l:← ↓ ↑ →移动光标

    $:定位到本行末尾

    ^:定位到本行开头

    w:光标跳到下一个字的开头

    b:光标跳到上一个字的开头

  • 删除

    n+x:光标所在位置开始向后删除n个字符

    n+X:光标所在位置开始向前删除n个字符

    dd:删除光标所在行

  • 替换

    n+r+输入字符:从光标所在位置开始,用n个输入字符替换原字符

  • 更改

    shift+~:光标所在位置大小写替换

2. 底行模式操作

进入底行模式之前,先按esc键确定在命令模式下,再按:进入第行模式

  • 列出行号

    set nu:输入set nu,会在文件中每一行前面列出行号

    set nonu:取消行号

  • 查找

    /关键字:先按/,再输入想查找的内容,按n会跳转到下一个匹配的

    ?关键字:先按/,再输入想查找的内容,按n会跳转到上一个匹配的

  • 保存文件

    w

  • 离开vim

    q

    q!

3. 视图模式和替换模式

  • 从命令模式按shift+r会进入替换模式,此时就可以进行文本、字符替换操作

  • 从命令模式按ctrl+v会进入视图模式

    hjkl会进行区域选择,按I进入插入模式,然后按输入//后立马按ESC回到命令模式,就可以实现批量注释

4. 总结

image-20251208195408371

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值