☰
【Linux系统】05 Linux开发工具(下)
2026/10/12 4:54:45 网站建设 项目流程

目录

1 make 与 Makefile 自动化构建

1.1 为什么需要 Makefile

1.2 Makefile 基础规则

1.3 make 工具推演执行逻辑

1.4 伪目标 .PHONY

1.5 Makefile 进阶语法

自定义变量

三大自动变量(高频面试)

wildcard 通配符 + 后缀替换

模式规则 %.o:%.c

1.6 多文件项目通用 Makefile 模板

​编辑

2 实战:Linux 终端进度条程序

2.1 \r回车 与 \n换行

2.2 完整进度条代码

​编辑

3 Git 版本控制基础

3.1 版本控制解决什么痛点

3.2 Git 简单历史

3.3 安装与基础配置

3.4 Github 基础三板斧

​编辑

4 gdb 调试器基础

4.1 debug 版本与 release 版本

gdb 常用核心命令

5 本篇小结

6 面试 & 实操高频问答

Q1 make 和 Makefile 关系?

Q2 .PHONY 伪目标作用?

Q3 $@ $^ $< 分别是什么?

Q4 \r 和 \n 区别,fflush 作用?

Q5 gdb 调试为什么编译要加‑g?


1 make 与 Makefile 自动化构建

1.1 为什么需要 Makefile

小项目只有一两个.c文件,可以直接手动敲 gcc 命令。 当项目源文件数量变多,每次修改源码手动敲编译命令非常麻烦。

  • make:命令行工具,用来解析 Makefile 文件规则
  • Makefile:文本文件,记录项目编译的依赖规则。

价值:写好 Makefile 之后,只输入make一条命令就自动编译;make 会对比文件修改时间,只重新编译被修改过的文件,不会全部重编译,提升编译效率。

1.2 Makefile 基础规则

每条规则格式:

目标: 依赖文件列表 Shell命令 # !!必须Tab制表符开头,不能用空格
  • 目标 (target):想要生成的文件,例如可执行程序
  • 依赖:生成目标所需要的文件
  • 依赖方法:Tab 开头 shell 指令,描述如何由依赖生成目标

简单示例,test.c源码:

#include <stdio.h> int main() { printf("hello Makefile!\n"); return 0; }

Makefile内容:

test:test.c gcc -o test test.c

终端执行:

make ./test

1.3 make 工具推演执行逻辑

  1. make 在当前目录寻找Makefile或者makefile;
  2. 读取文件,取第一条规则的目标作为终极目标;
  3. 判断目标文件是否存在:
    • 如果目标不存在:执行命令生成目标;
    • 如果目标已经存在:对比目标文件修改时间 和 所有依赖文件修改时间。
      • 任意依赖文件比目标新 → 执行命令重新编译;
      • 全部依赖比目标旧 → 什么都不做,提示is up to date。
  4. 如果依赖本身是另一条规则的目标,则递归先执行这条规则,生成依赖文件。

测试时间逻辑:

make #生成test make #输出 is up to date touch test.c #更新c文件时间 make #重新编译

1.4 伪目标.PHONY

clean目标,用来删除编译生成的中间文件与可执行程序:

clean: rm -f test *.o *.i *.s

问题:如果当前目录刚好存在名叫clean的普通文件,执行make clean不会执行 rm 命令!make 会认为 clean 文件已经是最新,不需要执行规则。

使用.PHONY把 clean 声明为伪目标: 伪目标:不在乎磁盘有没有同名文件,只要执行make clean,无条件执行对应命令,不做时间戳对比。

正确写法:

.PHONY:clean clean: rm -f test *.o *.i *.s

运行清理:

make clean

1.5 Makefile 进阶语法

自定义变量
CC=gcc RM=rm -f test:test.c $(CC) -o test test.c .PHONY:clean clean: $(RM) test

$(变量名)取出变量内容。

三大自动变量(高频面试)

表格

变量含义
$@当前规则的目标
$^全部依赖文件集合,自动去重
$<依赖列表第一个文件

改写:

CC=gcc RM=rm -f test:test.c $(CC) -o $@ $^ .PHONY:clean clean: $(RM) test
wildcard 通配符 + 后缀替换
  • wildcard *.c:获取当前目录所有.c文件名
  • $(SRC:.c=.o):把列表中.c后缀替换为.o
SRC=$(wildcard *.c) OBJ=$(SRC:.c=.o)
模式规则%.o:%.c

%代表通配任意文件名。含义:任意 xxx.o 文件依赖 xxx.c 源文件。

%.o:%.c $(CC) -c $< -o $@

命令前面加@,代表不在终端回显这条 shell 命令,静默执行。

%.o:%.c @$(CC) -c $< -o $@

1.6 多文件项目通用 Makefile 模板

可以直接复制用于多 c 文件小项目:

CC=gcc RM=rm -f TARGET=app SRC=$(wildcard *.c) OBJ=$(SRC:.c=.o) $(TARGET):$(OBJ) @$(CC) $^ -o $@ %.o:%.c @$(CC) -c $< -o $@ .PHONY:clean clean: @$(RM) $(OBJ) $(TARGET)

使用:

make make clean

注意:头文件.h不会被 wildcard 捕获,大型项目需要手动把头文件加入依赖。

2 实战:Linux 终端进度条程序

2.1\r回车 与\n换行

老式打字机模型理解:

  • \n换行:光标移动到下一行行首
  • \r回车:光标回到当前这一行的最开头,不向下换行

示例区分现象:

// 1 会sleep之后才打印hello printf("hello"); sleep(3); // 2 \n会刷新行缓冲 printf("hello\n"); sleep(3);

Linux stdout 是行缓冲,遇到\n才刷新缓冲区输出内容;没有换行,内容留在缓冲区,不会立刻打印。fflush(stdout);强制刷新标准输出缓冲区,立刻输出缓冲区内容。

倒计时 demo:

#include <stdio.h> #include <unistd.h> int main() { int i = 10; while(i >=0) { printf("%2d\r",i); fflush(stdout); sleep(1); i--; } printf("\n"); return 0; }

2.2 完整进度条代码

process.h

#pragma once #include <stdio.h> void process_v1(); void FlushProcess(double total, double current);

process.c

#include "process.h" #include <string.h> #include <unistd.h> #define NUM 101 #define STYLE '=' void process_v1() { char buffer[NUM]; memset(buffer, 0, sizeof(buffer)); const char *lable="|/-\\"; int len = strlen(lable); int cnt = 0; while(cnt <= 100) { printf("[%-100s][%d%%][%c]\r", buffer, cnt, lable[cnt%len]); fflush(stdout); buffer[cnt]= STYLE; cnt++; usleep(50000); } printf("\n"); } void FlushProcess(double total, double current) { char buffer[NUM]; memset(buffer, 0, sizeof(buffer)); const char *lable="|/-\\"; int len = strlen(lable); static int cnt = 0; int num = (int)(current*100/total); int i = 0; for(; i < num; i++) { buffer[i] = STYLE; } double rate = current/total; cnt %= len; printf("[%-100s][%.1f%%][%c]\r", buffer, rate*100, lable[cnt]); cnt++; fflush(stdout); }

main.c

#include "process.h" #include <unistd.h> double total = 1024.0; double speed = 1.0; void DownLoad() { double current = 0; while(current <= total) { FlushProcess(total, current); usleep(3000); current += speed; } printf("\ndownload Done\n"); } int main() { DownLoad(); return 0; }

配套简易 Makefile:

CC=gcc RM=rm -f TARGET=processbar SRC=$(wildcard *.c) OBJ=$(SRC:.c=.o) $(TARGET):$(OBJ) @$(CC) $^ -o $@ %.o:%.c @$(CC) -c $< -o $@ .PHONY:clean clean: @$(RM) $(OBJ) $(TARGET)

运行:

make ./processbar

3 Git 版本控制基础

3.1 版本控制解决什么痛点

写代码经常复制一大堆副本:v1、v2、最终版、最终版改改,版本混乱,分不清每版改了什么,回滚麻烦。 Git 是分布式版本控制系统:记录每一次文件修改历史,支持版本回退、多人协同开发。

3.2 Git 简单历史

Linux 内核社区早期使用商业 BitKeeper,2005 年合作终止。Linus Torvalds 开发 Git,目标:速度快、分布式、支持海量项目、强大分支管理。

3.3 安装与基础配置

CentOS 安装 git:

sudo yum install git -y git --version

首次使用配置用户名邮箱(提交记录会携带):

git config --global user.name "你的名字" git config --global user.email "你的邮箱"

3.4 Github 基础三板斧

  1. Github 网页注册账号,新建仓库New repository,复制仓库 https/ssh 地址。

  1. 克隆仓库到本地:
git clone 仓库地址
  1. 进入仓库目录,修改文件。
  2. 三板斧:
git add 文件名 # 将改动加入暂存区 git commit -m "写本次修改说明" # 提交到本地仓库 git push # 推送到远端Github

辅助常用命令:

git status #查看当前状态 git log #查看提交日志 git pull #拉取远端最新代码到本地

.gitignore文件:配置哪些文件不需要 git 管理,比如编译生成的可执行程序、中间.o文件。

4 gdb 调试器基础

4.1 debug 版本与 release 版本

gcc 默认生成 release 版本,没有调试信息,不能 gdb 调试。 想要使用 gdb,编译的时候必须加上‑g选项生成 debug 调试信息。

示例代码sum.c

#include <stdio.h> int Sum(int s, int e) { int result = 0; for(int i = s; i <= e; i++) { result += i; } return result; } int main() { int start = 1; int end = 100; printf("I will begin\n"); int n = Sum(start, end); printf("running done, result is: %d\n", n); return 0; }

编译带调试信息:

gcc -g sum.c -o sum gdb sum

gdb 常用核心命令

表格

命令功能
list/l查看源码,l 行号
run/r开始运行程序
break/b 行号设置断点
info breakpoints查看所有断点
delete d 断点编号删除断点
next/n逐过程,不进入函数
step/s逐语句,遇到函数进入函数内部
print/p 变量打印变量值
display 变量持续跟踪打印变量
continue/c运行到下一个断点
quit/q退出 gdb

5 本篇小结

  1. make/Makefile 实现自动化编译;目标、依赖、Tab 命令;.PHONY伪目标;$@ $^ $<自动变量。
  2. \r回到行首、\n换行;stdout 行缓冲,fflush强制刷新,实现终端进度条。
  3. git 分布式版本控制;add commit push三板斧,管理代码版本。
  4. gdb 调试:编译必须加‑g;掌握断点、next、step、print 基础调试命令。

6 面试 & 实操高频问答

Q1 make 和 Makefile 关系?

make 是可执行工具;Makefile 是保存编译规则的文本文件,make 读取该文件执行构建。

Q2 .PHONY 伪目标作用?

忽略文件时间戳,不管磁盘是否存在同名文件,执行 make 伪目标就无条件执行规则,典型用于 clean。

Q3 $@ $^ $< 分别是什么?

$@当前规则目标;$^全部依赖;$<第一个依赖。

Q4 \r 和 \n 区别,fflush 作用?

\n光标跳到下一行开头;\r光标回到本行开头;stdout 行缓冲,fflush 强制刷新缓冲区立刻输出内容。

Q5 gdb 调试为什么编译要加‑g?

-g生成调试符号信息,release 版本没有调试信息,无法 gdb 断点调试。

📚系列回顾: 04 上:yum + vim + gcc/g++ 04 下:make/Makefile + 进度条 + git + gdb 调试 后续预告:Linux 进程基础

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询