三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

linux基础:开发工具(上)

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下安装软件有两种方式:

  1. 下载源代码手动编译,步骤繁琐,还要处理大量依赖;
  2. 使用软件包:开发者提前编译好程序,类似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-ylrzsz
1.2.4 软件源相关

CentOS源配置文件目录:/etc/yum.repos.d/

  • CentOS‑Base.repo:基础官方源
  • epel.repo:扩展软件源,很多第三方软件在这里
    安装扩展源:
sudoyuminstall-yepel-release

Ubuntu对应命令参考

aptsearch lrzsz#搜索软件sudoaptinstall-ylrzsz#安装sudoaptremove-ylrzsz#卸载

2 Vim编辑器

2.1 vi与vim区别

vimvi的升级版本,完全兼容vi指令,增加语法高亮、可视化操作等新特性,我们日常开发直接用vim。

vim是多模式编辑器,这是和记事本最大区别,最核心掌握3种模式。

2.2 Vim三大核心模式

  1. 命令模式(普通模式 Normal):打开vim默认进入此模式,控制光标、复制、删除、切换其他模式,不能直接输入文字
  2. 插入模式(Insert):真正写代码、输入文字的模式。
  3. 底行模式(末行模式 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步,完整流程:

  1. 预处理(-E):宏替换、去掉注释、展开头文件,生成.i预处理文件
  2. 编译(-S):语法检查,翻译成汇编语言,生成.s汇编文件
  3. 汇编(-c):汇编转为机器二进制,生成.o目标文件
  4. 链接:把多个目标文件 + 系统库,合并生成最终可执行程序

平时直接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#运行程序./hello
3.2.4 比较

两套Makefile对比表

对比项上方分步版本(4阶段)下方注释单命令版本
编译命令拆分4条gcc:-E预处理、-S汇编、-c编译、链接1条gcc -o myproc myproc.c,gcc内部完成全部四阶段
磁盘中间文件生成myproc.imyproc.smyproc.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),函数实现不在我们写的代码中,来自系统库,链接阶段把库和我们的程序结合

  1. 动态库(.so)【gcc默认】
    程序运行的时候才加载库文件,多个程序共用一份库,磁盘占用小;
    缺点:运行环境必须存在这个库。

查看程序依赖哪些动态库:

ldd hello
  1. 静态库(.a)
    编译链接时,直接把库代码拷贝进可执行程序。
    优点:程序移植方便,运行不依赖外部库;
    缺点:生成程序体积大,多个程序会有多份库副本。

编译使用静态链接加‑static参数:

gcc hello.c-ohello_static-static

CentOS默认没有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#执行清理,删除生成的可执行程序

解读:

  1. myproc是最终目标,依赖main.c;如果main.c比myproc新,就执行后面gcc命令重新编译;
  2. .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内置):

  • $@:代表冒号左边的目标
  • $^:代表冒号右边全部依赖
  • $<:代表第一个依赖文件

执行:

makemakeclean

4.4 make的工作原理

  1. 执行make,在当前目录寻找Makefile/makefile
  2. 找到文件,读取第一个目标作为最终要生成的产物;
  3. 判断:目标文件是否存在,或者依赖文件的修改时间比目标更新;
  4. 如果需要更新,执行对应命令;如果依赖本身不存在,递归寻找规则生成依赖;
  5. 如果中途找不到依赖文件,直接报错终止。

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 files

5.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命令小坑(来自你的操作记录)

  1. touch project1:touch创建普通文件,不是文件夹,不能cd进去。
touchproject1cdproject1# 报错 Not a directory

✔创建文件夹用mkdirmkdir -p project1/src递归创建多级目录。

  1. 相对路径问题
# 当前在 ~/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#清理编译产物makeclean

5.5 扩展练习任务(课后实操)

  1. 修改fun1fun2里面printf内容,重新执行make,观察make只会重新编译改动的.c文件;
  2. 使用gcc分步编译:把每个.c编译为.o目标文件,再手动链接;
  3. 故意在code2.c写多一个main,复现multiple definition链接报错,理解链接期错误;
  4. 故意删掉main.c中的main函数,复现undefined reference to main

小结

  1. yum/apt负责软件安装卸载,解决软件依赖,切换国内镜像加速下载;
  2. vim核心掌握三种模式,记住常用移动、删除、复制命令,可以配置.vimrc美化编辑器;
  3. gcc编译四阶段:预处理→编译→汇编→链接;区分动态链接、静态链接;调试编译必须加‑g
  4. Makefile定义编译规则,make命令自动化编译;伪目标.PHONY用来做项目清理,学会内置自动变量简化脚本。
  5. 多文件项目实操重点
    • 整个C项目有且只能有1个main()函数,放在main.c;
    • gcc编译需要把所有用到的.c全部参与编译链接;
    • 链接报错大多是:缺少函数实现、重复定义、缺少main入口;
    • mkdir创建目录,touch创建普通文件,../代表上级目录。
← 返回列表