linux基础:开发工具(上)
文章目录
- Linux基础开发工具完全入门
- 1 yum软件包管理器
- 1.1 什么是软件包与yum
- 1.2 yum常用操作(CentOS)
- 1.2.1 查看软件包
- 1.2.2 安装软件
- 1.2.3 卸载软件
- 1.2.4 软件源相关
- 2 Vim编辑器
- 2.1 vi与vim区别
- 2.2 Vim三大核心模式
- 2.3 基础打开保存退出
- 2.4 命令模式高频命令
- 2.4.1 切换插入模式
- 2.4.2 光标移动
- 2.4.3 删除
- 2.4.4 复制粘贴
- 2.4.5 撤销与反撤销
- 2.4.6 查找
- 2.5 Vim简单配置
- 3 gcc/g++编译器
- 3.1 程序编译4个完整阶段
- 3.2 分步编译示例
- 3.2.1 预处理 `-E`
- 3.2.2 编译生成汇编 `-S`
- 3.2.3 汇编生成目标文件 `-c`
- 3.2.4 链接生成可执行程序
- 3.2.4 比较
- 3.3 静态链接与动态链接
- 3.4 gcc常用选项汇总
- 4 Makefile与make工具
- 4.1 为什么需要Makefile
- 4.2 最简单Makefile示例
- 4.3 多文件项目Makefile
- 4.4 make的工作原理
- 5 综合代码实操:多文件C项目实战
- 5.1 项目需求
- 5.1.1 规范创建项目目录
- 5.2 踩坑1:编译缺少main函数 / 重复定义main
- 错误命令1:只编译code1.c code2.c,不带main.c
- 错误命令2:如果code2.c里面不小心写了一个main函数
- ✔正确编译命令:带上全部源文件,包含main.c
- 5.3 踩坑2:Linux命令小坑(来自你的操作记录)
- 5.4 升级:给多文件项目写Makefile
- 5.5 扩展练习任务(课后实操)
- 小结
Linux基础开发工具完全入门
面向Linux初学者,讲解yum包管理器、vim编辑器、gcc/g++编译器、Makefile自动化构建工具,附带大量可直接复制的示例命令。
1 yum软件包管理器
1.1 什么是软件包与yum
在Linux下安装软件有两种方式:
- 下载源代码手动编译,步骤繁琐,还要处理大量依赖;
- 使用软件包:开发者提前编译好程序,类似Windows的安装包,存放在服务器。
yum就是CentOS/RHEL系列的软件包管理器,类比手机的应用商店,自动帮我们下载软件、解决依赖、安装、卸载。
补充:Ubuntu/Debian使用
apt作为包管理器,功能逻辑一致,只是命令不一样。
软件包之间会存在依赖:A软件运行需要B、C库,如果没有包管理器,要手动一个个装依赖,yum会自动处理这套关系。
国内镜像源:国外服务器访问慢,可以切换阿里云、清华镜像源,提升下载速度。
1.2 yum常用操作(CentOS)
⚠️注意:yum操作网络必须通畅,部分操作需要管理员权限
sudo;不能同时执行多个yum安装任务。
1.2.1 查看软件包
# 列出所有包,结合grep过滤想要找的软件yum list|greplrzsz包名字段解读:
x86_64:64位CPU架构;i686代表32位el7:代表CentOS7系统- 最后一列:代表这个软件来自哪个软件源
1.2.2 安装软件
# -y 自动确认安装,不用手动输入ysudoyuminstall-ylrzsz- 必须加
sudo,安装要修改系统目录; - 输出出现
complete代表安装成功。
1.2.3 卸载软件
sudoyum remove-ylrzsz1.2.4 软件源相关
CentOS源配置文件目录:/etc/yum.repos.d/
CentOS‑Base.repo:基础官方源epel.repo:扩展软件源,很多第三方软件在这里
安装扩展源:
sudoyuminstall-yepel-releaseUbuntu对应命令参考
aptsearch lrzsz#搜索软件sudoaptinstall-ylrzsz#安装sudoaptremove-ylrzsz#卸载2 Vim编辑器
2.1 vi与vim区别
vim是vi的升级版本,完全兼容vi指令,增加语法高亮、可视化操作等新特性,我们日常开发直接用vim。
vim是多模式编辑器,这是和记事本最大区别,最核心掌握3种模式。
2.2 Vim三大核心模式
- 命令模式(普通模式 Normal):打开vim默认进入此模式,控制光标、复制、删除、切换其他模式,不能直接输入文字。
- 插入模式(Insert):真正写代码、输入文字的模式。
- 底行模式(末行模式 Last‑line):保存、退出、查找、设置行号,输入冒号
:进入。
模式切换逻辑:
- 命令模式 → 插入模式:按
i/a/o - 插入模式 → 命令模式:按
ESC - 命令模式 → 底行模式:按
shift + ;(也就是:) - 底行模式 → 命令模式:按
ESC
2.3 基础打开保存退出
#打开/新建文件 test.cvimtest.c底行模式常用指令:
:w #保存 :wq #保存并退出 :q! #强制退出,不保存修改 :set nu #显示行号2.4 命令模式高频命令
2.4.1 切换插入模式
| 按键 | 作用 |
|---|---|
| i | 光标当前位置开始输入 |
| a | 光标下一个字符位置输入 |
| o | 新开一行,行首输入 |
2.4.2 光标移动
h 左 j 下 k 上 l 右 gg #跳到文档开头 G #跳到文档末尾 ^ #跳到当前行行首 $ #跳到当前行行尾 w #跳到下一个单词开头 b #跳到上一个单词开头 ctrl+f 向下翻页 ctrl+b 向上翻页 15G #直接跳转到第15行2.4.3 删除
x #删除光标所在字符 dd #删除光标整行 5dd #从当前行开始,向下删除5行2.4.4 复制粘贴
yy #复制当前一整行 6yy #复制向下6行 p #粘贴缓冲区内容到光标下方 yw #复制一个单词2.4.5 撤销与反撤销
u #撤销上一步操作 ctrl + r #撤销的反向操作(恢复被撤销的内容)2.4.6 查找
进入底行模式:
/hello #向下搜索hello,n跳转到下一个匹配 ?hello #向上搜索hello,n跳转到上一个匹配2.5 Vim简单配置
vim分为系统全局配置和用户私有配置
- 全局配置(所有用户生效):
/etc/vimrc - 用户私有配置(只对当前用户生效):家目录下
.vimrc
配置自己的vim:
#回到家目录cd~#编辑私有配置文件,没有就自动创建vim.vimrc写入下面配置:
syntax on "开启语法高亮 set nu "显示行号 set shiftwidth=4 "缩进4个空格 set expandtab "tab转为空格保存退出,重新打开vim配置立刻生效。
高阶可以安装插件,初学者先掌握原生配置。
3 gcc/g++编译器
gcc编译C语言,g++编译C++;gcc也可以编译C++,g++也能编译C。
3.1 程序编译4个完整阶段
C/C++源代码到可执行程序一共4步,完整流程:
- 预处理(-E):宏替换、去掉注释、展开头文件,生成
.i预处理文件 - 编译(-S):语法检查,翻译成汇编语言,生成
.s汇编文件 - 汇编(-c):汇编转为机器二进制,生成
.o目标文件 - 链接:把多个目标文件 + 系统库,合并生成最终可执行程序
平时直接
gcc test.c -o test会一次性走完4个步骤。
3.2 分步编译示例
源码hello.c
#include<stdio.h>intmain(){printf("hello gcc\n");return0;}3.2.1 预处理-E
gcc-Ehello.c-ohello.i执行结束得到hello.i,里面是展开头文件、去掉注释后的C代码。
3.2.2 编译生成汇编-S
gcc-Shello.i-ohello.s输出.s汇编代码文件,可以看懂汇编指令。
3.2.3 汇编生成目标文件-c
gcc-chello.s-ohello.o.o是二进制目标文件,机器可以识别,但还不能直接运行。
3.2.4 链接生成可执行程序
gcc hello.o-ohello#运行程序./hello3.2.4 比较
两套Makefile对比表
| 对比项 | 上方分步版本(4阶段) | 下方注释单命令版本 |
|---|---|---|
| 编译命令 | 拆分4条gcc:-E预处理、-S汇编、-c编译、链接 | 1条gcc -o myproc myproc.c,gcc内部完成全部四阶段 |
| 磁盘中间文件 | 生成myproc.i、myproc.s、myproc.o | 不产生.i/.s/.o中间文件,仅输出myproc |
| 依赖关系 | 链式依赖myproc→o→s→i→c,增量编译,修改某一级只执行后续步骤 | 直接依赖myproc:myproc.c,源码改动就完整编译一次 |
| clean删除内容 | rm -f *.i *.s *.o myproc,清理全部中间文件+可执行文件 | rm -f myproc,仅删除最终可执行程序 |
| 运行结果 | 最终生成的myproc可执行程序功能完全一致 | 和左侧运行效果一模一样 |
| 适用场景 | 学习gcc四阶段完整流程,观察每一步输出文件 | 日常实际项目使用,简洁高效 |
两套完整代码片段
分步版本(上方)
myproc:myproc.o gcc myproc.o -o myproc myproc.o:myproc.s gcc -c myproc.s -o myproc.o myproc.s:myproc.i gcc -S myproc.i -o myproc.s myproc.i:myproc.c gcc -E myproc.c -o myproc.i .PHONY:clean clean: rm -f *.i *.s *.o myproc单命令版本(下方注释)
myproc:myproc.c gcc -o myproc myproc.c .PHONY:clean clean: rm -f myproc💡核心结论:最终可执行程序运行效果完全相同,区别只在于是否把预处理、汇编、编译的中间产物输出到磁盘上。
3.3 静态链接与动态链接
程序调用库函数(如printf),函数实现不在我们写的代码中,来自系统库,链接阶段把库和我们的程序结合。
- 动态库(.so)【gcc默认】
程序运行的时候才加载库文件,多个程序共用一份库,磁盘占用小;
缺点:运行环境必须存在这个库。
查看程序依赖哪些动态库:
ldd hello- 静态库(.a)
编译链接时,直接把库代码拷贝进可执行程序。
优点:程序移植方便,运行不依赖外部库;
缺点:生成程序体积大,多个程序会有多份库副本。
编译使用静态链接加‑static参数:
gcc hello.c-ohello_static-staticCentOS默认没有C/C++静态库,需要安装:
sudoyuminstallglibc-static libstdc++-static-y
3.4 gcc常用选项汇总
| 参数 | 作用 |
|---|---|
| -E | 只做预处理 |
| -S | 编译到汇编代码 |
| -c | 汇编生成目标.o文件 |
| -o | 指定输出文件名 |
| -g | 加入调试信息,供gdb调试使用 |
| -static | 静态链接 |
| -Wall | 开启全部警告,写代码建议带上 |
| -O0 ~ O3 | 编译优化级别,O0无优化,O3最高优化 |
4 Makefile与make工具
4.1 为什么需要Makefile
如果项目有几十个.c文件,每次手动敲一大段gcc编译命令非常麻烦。
make:是一个命令工具;Makefile:写编译规则的文本文件;
二者配合实现自动化构建。只需要执行make一条命令,自动完成编译,还会智能判断哪些文件修改了,只重新编译改动的文件,提升编译效率。
4.2 最简单Makefile示例
项目:main.c,生成可执行文件myproc
新建名字叫Makefile的文件(大小写敏感,M大写)
#目标:依赖文件 myproc:main.c gcc -o myproc main.c #伪目标,清理编译产物 .PHONY:clean clean: rm -f myproc⚠️注意:
gcc前面必须是Tab缩进,不能用空格!
使用:
make#执行编译,生成myprocmakeclean#执行清理,删除生成的可执行程序解读:
myproc是最终目标,依赖main.c;如果main.c比myproc新,就执行后面gcc命令重新编译;.PHONY:clean声明clean是伪目标:不要去磁盘找叫clean的文件,永远执行clean下面的命令;伪目标不会被make自动执行,需要手动make clean调用。.PHONY 是直接忽略时间戳(时间轴)判断逻辑而直接执行,下方黄色发亮字体有解释
4.3 多文件项目Makefile
假设项目有main.c test.c两个源码,需要分别编译成.o再链接。
#变量定义 CC=gcc OBJ=main.o test.o BIN=app #最终可执行程序,依赖所有目标文件 $(BIN):$(OBJ) $(CC) -o $@ $^ #通用规则:所有.c生成同名.o %.o:%.c $(CC) -c $< -o $@ .PHONY:clean clean: rm -f $(OBJ) $(BIN)自动变量说明(Makefile内置):
$@:代表冒号左边的目标$^:代表冒号右边全部依赖$<:代表第一个依赖文件
执行:
makemakeclean4.4 make的工作原理
- 执行
make,在当前目录寻找Makefile/makefile; - 找到文件,读取第一个目标作为最终要生成的产物;
- 判断:目标文件是否存在,或者依赖文件的修改时间比目标更新;
- 如果需要更新,执行对应命令;如果依赖本身不存在,递归寻找规则生成依赖;
- 如果中途找不到依赖文件,直接报错终止。
make依靠目标文件与依赖文件的Modify修改时间(mtime)判断是否已经make过:当目标产物存在,且所有依赖源码的修改时间都早于目标产物的修改时间,就代表源码自上次编译后没有改动,输出
xxx is up to date不再执行编译;若源码被修改,其mtime更新晚于产物,则触发重新编译,make只比对mtime,不比对文件实际内容。
这里touch可重新更改时间,touch文件就行。
优势:只编译修改过的文件,大型项目节省大量编译时间。
5 综合代码实操:多文件C项目实战
基于你终端真实操作日志,模拟一个多文件C语言项目,体验项目目录规划、gcc编译报错排错、多文件编译,理解链接阶段常见错误。
5.1 项目需求
我们写一个多文件小项目:
code1.c/code1.h:实现函数fun1()code2.c/code2.h:实现函数fun2()main.c:程序唯一入口main(),调用fun1()、fun2()
5.1.1 规范创建项目目录
实操命令,可以直接复制运行
#回到家目录cd~# 创建标准项目目录结构:project/src存放源代码mkdir-pproject/src# 切换进入源码目录cdproject/src创建各个源码文件内容:code1.h
#pragmaoncevoidfun1();code1.c
#include"code1.h"#include<stdio.h>voidfun1(){printf("hi fun1()");}code2.h
#pragmaoncevoidfun2();code2.c
#include"code2.h"#include<stdio.h>voidfun2(){printf("hi fun2()");}main.c(唯一main函数,程序入口)
#include"code1.h"#include"code2.h"intmain(){fun1();fun2();return0;}目录结构,执行tree查看:
tree输出:
. ├── code1.c ├── code1.h ├── code2.c ├── code2.h └── main.c 0 directories, 5 files5.2 踩坑1:编译缺少main函数 / 重复定义main
错误命令1:只编译code1.c code2.c,不带main.c
gcc code1.c code2.c-ocode报错:
/usr/bin/ld: undefined reference to `main' collect2: error: ld returned 1 exit status✅错误原因:
链接阶段找不到程序入口
main函数!Linux C程序必须要有且仅有1个main作为入口。code1.c code2.c只是功能模块,没有main。
错误命令2:如果code2.c里面不小心写了一个main函数
gcc code1.c code2.c-ocode报错:
multiple definition of `main'; multiple definition of `fun1'✅错误原因:
重复定义!整个项目只能存在一份main函数;同一个全局函数不能多处实现。
业务功能写在code1/code2,main只允许写在main.c。
✔正确编译命令:带上全部源文件,包含main.c
gcc main.c code1.c code2.c-ocode#运行程序./code输出结果:
hi fun1()hi fun2()5.3 踩坑2:Linux命令小坑(来自你的操作记录)
touch project1:touch创建普通文件,不是文件夹,不能cd进去。
touchproject1cdproject1# 报错 Not a directory✔创建文件夹用
mkdir;mkdir -p project1/src递归创建多级目录。
- 相对路径问题
# 当前在 ~/project/libcdsrc bash: cd: src: No suchfileor directory当前在lib文件夹,src是lib的同级,不是子目录。
- 进入同级src:
cd ../src../代表上级目录;./代表当前目录
5.4 升级:给多文件项目写Makefile
在~/project/src下面创建Makefile
# 指定编译器 CC = gcc # 获取当前目录下所有的.c源文件 SRC := $(wildcard *.c) # 将所有.c文件名替换为.o目标文件 OBJ := $(SRC:.c=.o) # 最终生成的可执行程序名 BIN := code # 最终目标:可执行文件,依赖所有.o目标文件 $(BIN): $(OBJ) # $@ 代表目标文件($(BIN)),$^代表全部依赖文件($(OBJ)) $(CC) -o $@ $^ # 通用模式规则:所有 .c 文件编译生成对应的 .o 文件 %.o: %.c # $< 代表第一个依赖文件(即对应的.c源码) $(CC) -c $< # 声明clean为伪目标,不生成磁盘文件,总是执行 .PHONY: clean # 清理规则:删除所有目标文件和可执行程序 clean: rm -f $(OBJ) $(BIN)使用Makefile编译项目:
#一键编译全部文件make#运行./code#清理编译产物makeclean5.5 扩展练习任务(课后实操)
- 修改
fun1、fun2里面printf内容,重新执行make,观察make只会重新编译改动的.c文件; - 使用gcc分步编译:把每个
.c编译为.o目标文件,再手动链接; - 故意在code2.c写多一个main,复现
multiple definition链接报错,理解链接期错误; - 故意删掉main.c中的main函数,复现
undefined reference to main。
小结
- yum/apt负责软件安装卸载,解决软件依赖,切换国内镜像加速下载;
- vim核心掌握三种模式,记住常用移动、删除、复制命令,可以配置
.vimrc美化编辑器; - gcc编译四阶段:预处理→编译→汇编→链接;区分动态链接、静态链接;调试编译必须加
‑g; - Makefile定义编译规则,make命令自动化编译;伪目标
.PHONY用来做项目清理,学会内置自动变量简化脚本。 - 多文件项目实操重点
- 整个C项目有且只能有1个
main()函数,放在main.c; - gcc编译需要把所有用到的
.c全部参与编译链接; - 链接报错大多是:缺少函数实现、重复定义、缺少main入口;
mkdir创建目录,touch创建普通文件,../代表上级目录。
- 整个C项目有且只能有1个
