Linux开发必备:yum/vim/gcc/make全攻略
目录
1.学习yum、apt⼯具,进⾏软件安装
1-1 什么是软件包
1-2 yum/apt具体操作
2. 编辑器Vim
2-1 Linux编辑器-vim的引入
2-2 vim的基本概念
2-3 vim的基本操作
2-4 vim正常模式命令集
2-5 vim末⾏模式命令集
3. 编译器gcc/g++
3-1 背景知识
3-2 gcc编译选项
3-3 动态链接和静态链接
3-4 静态库和动态库
3-5 gcc其他常⽤选项-了解即可
4.⾃动化构建-make/Makefile
4-1背景
4-2 基本使⽤
4-3 适度扩展语法
1.学习yum、apt⼯具,进⾏软件安装
1-1 什么是软件包
• 在Linux下安装软件,⼀个通常的办法是下载到程序的源代码,并进⾏编译,得到可执⾏程序.
• 但是这样太⿇烦了,于是有些⼈把⼀些常⽤的软件提前编译好,做成软件包(可以理解成windows上 的安装程序)放在⼀个服务器上,通过包管理器可以很⽅便的获取到这个编译好的软件包,直接进⾏安 装.
• 软件包和软件包管理器,就好⽐"App"和"应⽤商店"这样的关系.
• yum(YellowdogUpdater,Modified)是Linux下⾮常常⽤的⼀种包管理器主要应⽤在Fedora, RedHat,Centos等发⾏版上.
• Ubuntu:主要使⽤apt(Advanced Package Tool)作为其包管理器。apt同样提供了⾃动解决依 赖关系、下载和安装软件包的功能。
1-2 yum/apt具体操作
1-2-1 查看软件包
通过yum list命令可以罗列出当前⼀共有哪些软件包.由于包的数⽬可能⾮常之多,这⾥我们需要使⽤ grep命令只筛选出我们关注的包.例如:
# Centos
$ yum list | grep lrzsz
lrzsz.x86_64 0.12.20-36.el7 @base
# Ubuntu
$ apt search lrzsz
Sorting... Done
Full Text Search... Done
cutecom/focal 0.30.3-1build1 amd64Graphical serial terminal, like minicom
lrzsz/focal,now 0.12.21-10 amd64 [installed]Tools for zmodem/xmodem/ymodem file transfer$ apt show lrzsz
Package: lrzsz
Version: 0.12.21-10
Priority: optional
Section: universe/comm
Origin: Ubuntu
Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
Original-Maintainer: Martin A. Godisch <godisch@debian.org>
执行命令 $ yum list | grep lrzsz
,通过 yum list
列出所有软件包并过滤包含 lrzsz
的条目;
执行命令 $ apt search lrzsz
,通过 apt
搜索 lrzsz
相关软件包;
执行命令 $ apt show lrzsz
,查看 lrzsz
软件包的详细信息。
1-3-2 安装软件
通过yum,我们可以通过很简单的⼀条命令完成gcc的安装.
# Centos
$ sudo yum install -y lrzsz
# Ubuntu
$ sudo apt install -y lrzsz
• yum/apt会⾃动找到都有哪些软件包需要下载,这时候敲"y"确认安装.
• 出现"complete"字样或者中间未出现报错,说明安装完成.
注意事项:
• 安装软件时由于需要向系统⽬录中写⼊内容,⼀般需要sudo或者切到root账⼾下才能完成.
• yum/apt安装软件只能⼀个装完了再装另⼀个.正在yum/apt安装⼀个软件的过程中,如果再尝试⽤ yum/apt安装另外⼀个软件,yum/apt会报错.
1-2-3 卸载软件
1 # Centos
sudo yum remove [-y] lrzsz
# Ubuntu
sudo apt remove [-y] lrzsz
2. 编辑器Vim
2-1 Linux编辑器-vim的引入
vi/vim的区别简单点来说,它们都是多模式编辑器,不同的是vim是vi的升级版本,它不仅兼容vi的所 有指令,⽽且还有⼀些新的特性在⾥⾯。例如语法加亮,可视化操作不仅可以在终端运⾏,也可以运 ⾏于x window、mac os、windows。本文统⼀按照vim来进⾏讲解。
2-2 vim的基本概念
我们讲解vim的三种模式(其实有好多模式,⽬前掌握这3种即可),分别是命令模式(command mode)、插⼊模式(Insert mode)和底⾏模式(last line mode),各模式的功能区分如下:
• 正常/普通/命令模式
控制屏幕光标的移动,字符、字或⾏的删除,移动复制某区段及进⼊Insert mode下,或者到 last line mode;
• 插⼊模式
只有在Insert mode下,才可以做⽂字输⼊,按「ESC」键可回到命令⾏模式。该模式是我们后⾯⽤ 的最频繁的编辑模式。
• 末⾏模式
⽂件保存或退出,也可以进⾏⽂件替换,找字符串,列出⾏号等操作。 在命令模式下,*shift+:*即可进⼊该模式。要查看你的所有模式:打开vim,底⾏模式直接输⼊ :help vim-modes
图解:
2-3 vim的基本操作
• 进⼊vim,在系统提⽰符号输⼊vim及⽂件名称后,比如$ vim test.c ,就进⼊vim全屏幕编辑画⾯:
不过有⼀点要特别注意,就是你进⼊vim之后,是处于[正常模式],你要切换到[插⼊模式]才能够 输⼊⽂字。、
• [正常模式]切换⾄[插⼊模式]
• 输⼊a
• 输⼊i
• 输⼊o
• [插⼊模式]切换⾄[正常模式]
⽬前处于[插⼊模式],就只能⼀直输⼊⽂字,如果发现输错了字,想⽤光标键往回移动,将该字删 除,可以先按⼀下「ESC」键转到[正常模式]再删除⽂字。当然,也可以直接删除。
• [正常模式]切换⾄[末⾏模式]
[shift + ;],其实就是输⼊「:」
• 退出vim及保存⽂件,要在[正常模式]下,按⼀下「:」冒号键进⼊底行模式,然后:
• :w(保存当前⽂件)
• :wq(输⼊「wq」,存盘并退出vim)
• :q!(输⼊q!,不存盘强制退出vim)
2-4 vim正常模式命令集
1.插⼊模式
• 按「i」切换进⼊插⼊模式「insert mode」,按“i”进⼊插⼊模式后是从光标当前位置开始输⼊ ⽂件;
• 按「a」进⼊插⼊模式后,是从⽬前光标所在位置的下⼀个位置开始输⼊⽂字;
• 按「o」进⼊插⼊模式后,是插⼊新的⼀⾏,从新一行的⾏⾸开始输⼊⽂字。
2.从插⼊模式切换为命令模式
按「ESC」键
3.移动光标
• vim可以直接⽤键盘上的光标来上下左右移动,但正规的vim命令模式下是⽤⼩写英⽂字⺟「h」、「j」、 「k」、「l」,分别控制光标左、下、上、右移⼀格;
• 按「G」:移动到⽂章的最后
• 按[gg]:进⼊到⽂本开始
• 按「 $ 」:移动到光标所在⾏的“⾏尾”
• 按「^」:移动到光标所在⾏的“⾏⾸”
• 按「w」:光标跳到下个字的开头
• 按「e」:光标跳到下个字的字尾
• 按「b」:光标回到上个字的开头
• 按「#l」:光标移到该⾏的第#个位置,如:5l,56l
• 按「ctrl」+「b」:屏幕往“后”移动⼀⻚
• 按「ctrl」+「f」:屏幕往“前”移动⼀⻚
• 按「ctrl」+「u」:屏幕往“后”移动半⻚
• 按「ctrl」+「d」:屏幕往“前”移动半⻚
4.删除⽂字
• 「x」:每按⼀次,删除光标所在位置的⼀个字符
• 「#x」:例如,「6x」表⽰删除光标所在位置的“后⾯(包含⾃⼰在内)”6个字符
• 「X」:⼤写的X,每按⼀次,删除光标所在位置的“前⾯”⼀个字符
• 「#X」:例如,「20X」表⽰删除光标所在位置的“前⾯”20个字符
• 「dd」:删除光标所在⾏
• 「#dd」:从光标所在⾏开始删除#⾏
5.复制
• 「yw」:将光标所在之处到字尾的字符复制到缓冲区中。
• 「#yw」:从光标所在处复制#个字到缓冲区(字指的是单词)。
• 「yy」:复制光标所在⾏到缓冲区。
• 「#yy」:例如,「6yy」表⽰拷⻉从光标所在的该⾏“往下数”6⾏⽂字。
• 「p」:将缓冲区内的字符贴到光标所在位置。注意:所有与“y”有关的复制命令都必须 与“p”配合才能完成复制与粘贴功能。
6.替换
• 「r」:替换光标所在处的字符。
• 「R」:替换光标所到之处的字符,直到按下「ESC」键为⽌。
7.撤销上⼀次操作
• 「u」:如果您误执⾏⼀个命令,可以⻢上按下「u」,回到上⼀个操作。按多次“u”可以执⾏ 多次回复。
• 「ctrl + r」:撤销的恢复
8.更改
• 「cw」:更改光标所在处的字到字尾处 (表现出来是删除了这段并进入插入模式)
• 「c#w」:例如,「c3w」表⽰更改3个字
9.跳⾄指定的⾏
• 「ctrl」+「g」列出光标所在⾏的⾏号。
• 「#G」:例如,「15G」,表⽰移动光标⾄⽂章的第15⾏⾸。
2-5 vim末⾏模式命令集
在使⽤末⾏模式之前,请记住先按「ESC」键确定您已经处于正常模式,再按「:」冒号即可进⼊末⾏ 模式。
1.列出⾏号
• 「set nu」:输⼊「set nu」后,会在⽂件中的每⼀⾏前⾯列出⾏号。
2.跳到⽂件中的某⼀⾏
• 「#」:「#」号表⽰⼀个数字,在冒号后输⼊⼀个数字,再按回⻋键就会跳到该⾏了,如输⼊数字 15,再回⻋,就会跳到⽂章的第15⾏。
3.查找字符
• 「/关键字」:先按「/」键,再输⼊您想寻找的字符,如果第⼀次找的关键字不是您想要的,可以 ⼀直按「n」会往后寻找到您要的关键字为⽌。
• 「?关键字」:先按「?」键,再输⼊您想寻找的字符,如果第⼀次找的关键字不是您想要的,可 以⼀直按「n」会往前寻找到您要的关键字为⽌。
注意:∕和?查找的区别:前者是向下查找,首次出现的是整个页面的第一个,按n就是向下遍历;后者是向上查找,首次出现的是整页的最后一个,按n向上遍历;
4.保存⽂件
• 「w」:在冒号输⼊字⺟「w」就可以将⽂件保存起来
5.离开vim
• 「q」:按「q」就是退出,如果⽆法离开vim,可以在「q」后跟⼀个「!」强制离开vim。
• 「wq」:⼀般建议离开时,搭配「w」⼀起使⽤,这样在退出的时候还可以保存⽂件。
3. 编译器gcc/g++
3-1 背景知识
1.预处理(进⾏宏替换/去注释/条件编译/头⽂件展开等)
2.编译(⽣成汇编)
3.汇编(⽣成机器可识别代码)
4.连接(⽣成可执⾏⽂件或库⽂件)
3-2 gcc编译选项
格式 gcc [选项] 要编译的⽂件 [选项] [⽬标⽂件]
3-2-1 预处理(进⾏宏替换)
• 预处理功能主要包括宏定义,⽂件包含,条件编译,去注释等。
• 预处理指令是以#号开头的代码⾏。
• 实例:gcc –E hello.c –o hello.i
• 选项“-E”,该选项的作⽤是让 gcc 在预处理结束后停⽌编译过程。
3-2-2 编译(⽣成汇编)
• 在这个阶段中,gcc ⾸先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的⼯作, 在检查⽆误后,gcc把代码翻译成汇编语⾔。
• ⽤⼾可以使⽤“-S”选项来进⾏查看,该选项只进⾏编译⽽不进⾏汇编,⽣成汇编代码。
• 实例: gcc –S hello.i –o hello.s
3-2-3 汇编(⽣成机器可识别代码)
• 汇编阶段是把编译阶段⽣成的“.s”⽂件转成⽬标⽂件
• 读者在此可使⽤选项“-c”就可看到汇编代码已转化为“.o”的⼆进制⽬标代码了
• 实例: gcc –c hello.s –o hello.o
3-2-4 连接(⽣成可执⾏⽂件或库⽂件)
• 在成功编译之后,就进⼊了链接阶段。
• 实例:gcc hello.o –o hello
3-3 动态链接和静态链接
在我们的实际开发中,不可能将所有代码放在⼀个源⽂件中,所以会出现多个源⽂件,⽽且多个源⽂ 件之间不是独⽴的,⽽会存在多种依赖关系,如⼀个源⽂件可能要调⽤另⼀个源⽂件中定义的函数, 但是每个源⽂件都是独⽴编译的,即每个*.c⽂件会形成⼀个*.o⽂件,为了满⾜前⾯说的依赖关系,则 需要将这些源⽂件产⽣的⽬标⽂件进⾏链接,从⽽形成⼀个可以执⾏的程序。
静态链接是指在编译链接阶段将目标文件和所需的库文件合并成一个可执行文件。其特点是生成的可执行文件包含了所有需要的代码和数据,不依赖外部的库文件,可以独立运行。静态链接库工程编译后会生成.lib文件,使用时直接将库中的全部函数链接到目的程序中,运行时不再需要库文件即可直接运行。
静态链接的缺点:
• 浪费空间:因为每个可执⾏程序中对所有需要的⽬标⽂件都要有⼀份副本,所以如果多个程序对 同⼀个⽬标⽂件都有依赖,如多个程序中都调⽤了printf()函数,则这多个程序中都含有 printf.o,所以同⼀个⽬标⽂件在内存存在多个副本;
• 更新⽐较困难:因为每当库函数的代码修改了,这个时候就需要重新进⾏编译链接形成可执⾏程 序。但是静态链接的优点就是,在可执⾏程序中已经具备了所有执⾏程序所需要的任何东西,在 执⾏的时候运⾏速度快。
动态链接的出现解决了静态链接中提到问题。动态链接的基本思想是把程序按照模块拆分成各个相对 独⽴部分,在程序运⾏时才将它们链接在⼀起形成⼀个完整的程序,⽽不是像静态链接⼀样把所有程序模块都链接成⼀个单独的可执⾏⽂件。动态链接库可以被多个应用程序共享使用。
这种方式生成的可执行文件体积较小,但运行时需要依赖外部库文件。
在这⾥涉及到⼀个重要的概念:库
• 我们的C程序中,并没有定义“printf”的函数实现,且在预编译中包含的“stdio.h”中也只有该 函数的声明,⽽没有定义函数的实现,那么,是在哪⾥实“printf”函数的呢?
• 最后的答案是:系统把这些函数实现都被做到名为libc.so.6的库⽂件中去了,在没有特别指定 时,gcc会到系统默认的搜索路径“/usr/lib”下进⾏查找,也就是链接到libc.so.6库函数中去,这样就能实现函数“printf”了,⽽这也就是链接的作⽤。
3-4 静态库和动态库
• 静态库是指编译链接时,把库⽂件的代码全部加⼊到可执⾏⽂件中,因此⽣成的⽂件⽐较⼤,但在运 ⾏时也就不再需要库⽂件了。其后缀名⼀般为“.a”;
• 动态库与之相反,在编译链接时并没有把库⽂件的代码加⼊到可执⾏⽂件中,⽽是在程序执⾏时由 运⾏时链接⽂件加载库,这样可以节省系统的开销。动态库⼀般后缀名为“.so”,如前⾯所述的 libc.so.6就是动态库。gcc在编译时默认使⽤动态库。完成了链接之后,gcc就可以⽣成可执⾏⽂ 件,如下所⽰。 gcc hello.o –o hello
注意: Linux下,动态库XXX.so,静态库XXX.a; Windows下,动态库XXX.dll,静态库XXX.lib;
3-5 gcc其他常⽤选项-了解即可
• -E 只激活预处理,这个不⽣成⽂件,你需要把它重定向到⼀个输出⽂件⾥⾯
• -S 编译到汇编语⾔不进⾏汇编和链接
• -c 编译到⽬标代码
• -o ⽂件输出到 ⽂件
• -static 此选项对⽣成的⽂件采⽤静态链接
• -g ⽣成调试信息。GNU 调试器可利⽤该信息。
• -shared 此选项将尽量使⽤动态库,所以⽣成⽂件⽐较⼩.
• -O0 • -O1 • -O2 • -O3编译器的优化选项的4个级别,-O0表⽰没有优化,-O1为缺省值,-O3优化级别最⾼
• -w 不⽣成任何警告信息。
• -Wall ⽣成所有警告信息。
4.⾃动化构建-make/Makefile
4-1背景
• 会不会写makefile,从⼀个侧⾯说明了⼀个⼈是否具备完成⼤型⼯程的能⼒
• ⼀个⼯程中的源⽂件不计数,其按类型、功能、模块分别放在若⼲个⽬录中,makefile定义了⼀ 系列的规则来指定,哪些⽂件需要先编译,哪些⽂件需要后编译,哪些⽂件需要重新编译,甚⾄ 于进⾏更复杂的功能操作
• makefile带来的好处就是⸺⸺“⾃动化编译”,⼀旦写好,只需要⼀个make命令,整个⼯程完全 ⾃动编译,极⼤的提⾼了软件开发的效率。
• make是⼀个命令⼯具,是⼀个解释makefile中指令的命令⼯具,⼀般来说,⼤多数的IDE都有这 个命令,⽐如:Delphi的make,VisualC++的nmake,Linux下GNU的make。可⻅,makefile 都成为了⼀种在⼯程⽅⾯的编译⽅法。
• make是⼀条命令,makefile是⼀个⽂件,两个搭配使⽤,完成项⽬⾃动化构建。
4-2 基本使⽤
实例代码:
#include <stdio.h>
int main()
{printf("hello Makefile!\n");return 0;
}
Makefile⽂件:
myproc:myproc.cgcc -o myproc myproc.c.PHONY:clean
clean:rm -f myproc
依赖关系
• 上⾯的可执行⽂件myproc,它依赖myproc.c
依赖⽅法
gcc -o myproc myproc.c
makefile基本格式:
清理项目:
伪对象的作用有两个,1. 使目标对象无论如何都要重新生成。2. 并不生成目标文件,而是为了执行一些指令。
make是如何⼯作的,在默认的⽅式下,也就是我们只输⼊make命令。那么:
1. make会在当前⽬录下找名字叫“Makefile”或“makefile”的⽂件。
2. 如果找到,它会找⽂件中的第⼀个⽬标⽂件(target),在上⾯的例⼦中,他会找到 myproc 这 个⽂件,并把这个⽂件作为最终的⽬标⽂件。makefile文件,会被make从上到下开始扫描,第一个目标名,是缺省要形成的.如果我们想执行其他组的依赖关系和方法,则make+name
3. 如果 myproc ⽂件不存在,或是 myproc 所依赖的后⾯的 myproc.o ⽂件的⽂件修改时间要 ⽐ myproc 这个⽂件新(可以⽤ touch 测试),那么,他就会执⾏后⾯所定义的命令来⽣成 myproc 这个⽂件。
4. 如果 myproc 所依赖的 myproc.o ⽂件不存在,那么 make 会在当前⽂件中找⽬标为 myproc.o ⽂件的依赖性,如果找到则再根据那⼀个规则⽣成 myproc.o ⽂件。(这有点像⼀ 个堆栈的过程)
即:make解释makefile的时候,是会自动推导的,一直推导,不执行依赖方法.直到推导到依赖文件存在为止,然后逆向的执行所有依赖方法(类似栈堆)
5. 这就是整个make的依赖性,make会⼀层⼜⼀层地去找⽂件的依赖关系,直到最终编译出第⼀个 ⽬标⽂件。
6.在找寻的过程中,如果出现错误,⽐如最后被依赖的⽂件找不到,那么make就会直接退出,并 报错,⽽对于所定义的命令的错误,或是编译不成功,make根本不理。make makefile在执行gcc命令的时候,如果发生了语法错误,就会终止推导过程
7.make只管⽂件的依赖性,即,如果在我找了依赖关系之后,冒号后⾯的⽂件还是不在,那么对 不起,我就不⼯作啦。
8.make默认只形成一个可执行程序,那么如何形成多个.exe?
问题引入:当我们编译一次程序后再次编译,会发现系统提示你已经是最新版本了,但是加上PHONY就可以反复编译,为什么?
gcc会进行时间对比,文件有自己的Modify(修改时间),由于一般情况下源文件比可执行文件的时间“旧”,所以就不再编译,如果修改时间新于可执行文件,那么可以编译。
因此PHONY的作用是让gcc忽略时间对比,所以可以反复编译
★为啥clean文件无论有没有PHONY都可以反复执行呢?因为rm本来就不关心时间
4-3 适度扩展语法
BIN=proc.exe # 定义变量
CC=gcc
#SRC=$(shell ls *.c) # 采⽤shell命令⾏⽅式,获取当前所有.c⽂件名
SRC=$(wildcard *.c) # 或者使⽤ wildcard 函数,获取当前所有.c⽂件名
OBJ=$(SRC:.c=.o) # 将SRC的所有同名.c 替换 成为.o 形成⽬标⽂件列表
LFLAGS=-o # 链接选项
FLAGS=-c # 编译选项
RM=rm -f # 引⼊命令
$(BIN):$(OBJ) @$(CC) $(LFLAGS) $@ $^ # $@:代表⽬标⽂件名。 $^: 代表依赖⽂件列表 @echo "linking ... $^ to $@"
%.o:%.c # %.c 展开当前⽬录下所有的.c。 %.o: 同时展开同
名.o@$(CC) $(FLAGS) $< # %<: 对展开的依赖.c⽂件,⼀个⼀个的交给gcc。 @echo "compling ... $< to $@" # @:不回显命令
.PHONY:clean
clean:$(RM) $(OBJ) $(BIN) # $(RM): 替换,⽤变量内容替换它 .PHONY:test
test: @echo $(SRC) @echo $(OBJ)