当前位置: 首页 > news >正文

快速上手Linux基础开发工具

目录

软件包管理器

概念理解

用法示例 - 以yum为例

vim

模式的切换

常用操作

插件和配置

gcc/g++

gdb

make / makefile


软件包管理器

概念理解

在Linux下安装软件的话,一个比较原始的办法是下载程序的源代码,然后进行编译,进而得到可执行程序,然后就可以运行这个软件了。但是这种做法太麻烦了,于是就有些人把一些常用的软件提前编译好,做成软件包,放到服务器上,通过包管理器可以很方便的获取到这个编译好的软件包,直接进行安装即可。而负责管理这些软件包的东西就叫软件包管理器。软件包和软件包管理器之间的关系,就好比手机上的 "App" 和 "应用商店" 这样的关系。

yum的实现过程大致可以概括为如下步骤:

此引用部分摘自:linux网络服务-部署yum仓库 - 掘金


先在yum服务器上创建 yum repository(仓库),在仓库中事先存储了众多rpm包,以及包的相关的元数据文件(放置于特定目录repodata下,内含有软件的依赖关系和软件的位置),当yum客户端利用yum/dnf工具进行安装时包时,会自动下载repodata中的元数据,查询元数据是否存在相关的包及依赖关系,自动从仓库中找到相关包下载并安装

而不同的Linux发行版本通常使用不同的软件包管理器来管理和安装软件包。以下是一些常见的 Linux发行版本及其对应的软件包管理器:

Ubuntu 和 Debian,使用 apt 作为软件包管理器。

CentOS 和 Red Hat,使用 yum 或 dnf 作为软件包管理器。在较新的版本中(CentOS 8和Red Hat 8及其之后),dnf 更为常见。

Fedora,使用 dnf 作为默认的软件包管理器。

openSUSE,使用 zypper 作为软件包管理器。

Arch Linux,使用 pacman 作为软件包管理器。

Manjaro,也是基于 Arch Linux,所以同样使用 pacman 作为软件包管理器。

Linux Mint,通常使用 apt,类似于 Ubuntu。

注意,这些发行版本中的软件包管理器可能会有不同的命令和选项,因此在使用时需要查阅相关文档或指南以获取详细信息。

用法示例 - 以yum为例

yum源

yum仓库,俗称yum源,用于存放各种的软件包。需要安装软件的计算机连接到指定yum仓库来安装软件包。yum源就相当于一个软件包管理器,类似于一个软件管家,而yum源又有分为本地yum源和网络yum源,绝大多数情况下我们使用的是网络yum源。
如果我们安装的是官方的系统镜像的话,其使用的网络yum源基本都是国外官方的,但国外的下载软件速度非常慢,很多情况下都无法下载。所以国内一些大公司会做镜像,以同步国外的软件。 所以我们可以配置使用国内的yum镜像源(如腾讯源、阿里源、华为源等)。

配置yum源的操作 - 以centos7,腾讯源为例:

首先我们直接网上搜索“腾讯源”,然后打开这个网站:腾讯软件源 (tencent.com)

接着找到centos,然后点击右侧的查看:

然后按照网页提示就可以直接安装了,它已经贴心的把指令告诉我们了。CentOS (tencent.com) 腾讯软件源icon-default.png?t=N7T8https://mirrors.tencent.com/help/centos.html

yum的语法格式

yum [options] [command] [package ...]

参数说明:

options: 选项,选项包括-h,-y,-q等等。

command: 要进行的操作。

package: 安装的包名。

常用选项:

-h:显示帮助信息

-y:对所有的提问都回答“yes”

-c:指定配置文件

-q:安静模式

-v:详细模式

-d:设置调试等级(0-10)

-e:设置错误等级(0-10)

-R:设置yum处理一个命令的最大等待时间

-C:完全从缓存中运行,而不去下载或者更新任何头文件

yum的常用命令

命令作用
yum list查询所有可安装的软件包
yum list <package_name>查询指定软件包的安装情况
yum info查询所有可安装软件包的详细信息
yum info <package_name>查询指定软件包的详细信息
yum list updates列出所有可更新的软件清单
yum list installed列出所有已安装的软件清单
yum update更新所有软件包(更新所有包同时,也更新软件和系统内核)
yum -y upgrade更新所有软件包(只更新所有包,不更新软件和系统内核)
yum update <package_name>更新指定软件包
yum install <package_name>安装指定软件包
yum remove <package_name>删除指定软件包
yum search <keyword>查找指定软件包

yum makecache

刷新缓存。把服务器的包信息下载到本地电脑缓存起来,makecache建立一个缓存。以后用install时就在缓存中搜索,提高了速度。配合yum -C search xxx使用,不用联网检索就能查找软件信息。
yum makecache fast将软件包信息提前在本地索引缓存,用来提高搜索安装软件的速度,执行这个命令可以提升yum安装的速度。
yum clean / yum clean all清除缓存目录下的软件包及旧的 headers。yum 会把下载的软件包和header存储在cache中而不自动删除。可以使用yum clean指令清除索引缓存和下载包的缓存。
yum clean packages清除缓存目录下的软件包
yum clean headers清除缓存目录下的 headers
yum clean oldheaders清除缓存目录下旧的 headers

vim

注意,这里只是简单的解释vim的一些基础用法,使得我们可以快速上手使用vim。如果想要更深层次的学习vim,可以自行探索,这里我推荐一个很不错的教程:(这个人的主页也有很多关于vim的相关内容,感兴趣的话可以好好看看)Learn-Vim(the Smart Way) 中文翻译icon-default.png?t=N7T8https://github.com/wsdjeg/Learn-Vim_zh_cn

如果觉得上面的内容太多了,也可以看一下这个:

Vim 命令速查表 - Chloneda - 博客园 (cnblogs.com)icon-default.png?t=N7T8https://www.cnblogs.com/chloneda/p/vim-cheatsheet.html当然,也可以参考这张很经典的图片:

模式的切换

下面就让我们来快速上手使用vim。首先,vim有很多模式,不同的模式下对应着不同的功能,虽然vim的模式有十几个但实际生活中最常用的也就3个:normal(命令)模式、command(底行)模式、insert(插入)模式,当然还有诸如v-block(视图)模式、replace(替换)模式等。

可以说,命令模式是vim中最基础的模式。首先,进入vim时默认的就是命令模式。而且,想要切换到其它模式,是必须在命令模式下进行的。下面就让我们来了解一下如何切换到其它模式。

首先,在命令模式下按i、a或o是可以进入到插入模式的,i是从当前光标下开始,a是光标后移一个,o是在下面另开一行。插入模式下就可以进行我们正常的写入了。在命令模式下按 shift+; 也就是打出冒号 ':' 就可以进入到底行模式。vim的一些操作,比如退出就是需要在低行模式下进行的。
按 Ctrl+v 是进入视图模式(v是大小写都可以),其中在视图模式下按shift+i、a、o等是在视图模式下进入插入模式,视图模式下可以批量对文本进行操作。输入大写的R(即shift+r)是进入到替换模式。替换模式下,每次输入的字符都会替换掉光标所在位置的字符。而对于任何模式下回到命令模式的情况,都是只需要按键盘左上角的Esc即可。

常用操作

0、进入vim

# 直接启动vim
vim # 打开单个文件
vim file# 同时打开多个文件
vim file1 file2 file3 ...

1、进入到插入模式

i  在当前位置生前插入

I  在当前行首插入

a  在当前位置后插入

在当前行尾插入

在当前行之后插入一行

O  在当前行之前插入一行

s  删除当前字符并进入插入模式

删除当前行并进入插入模式

2、光标的移动

左移一个字符,nh  左移n个字符

j   下移一个字符,nj   下移n个字符
上移一个字符,nk  上移n个字符
l   右移一个字符,nl   右移n个字符
上面的这四个hjkl就对应着键盘右侧的 ←↓↑→ 方向键。

gg / [[   移动到文件头
G(shift + g) / ]]   移动到文件尾

nG   移动到第n行

:n   移动到第n行

0   数字0,移动到本行第一个字符上,

功能键HOME   移动到本行第一个字符,同0健。

^ (shitf+6)   移动到本行第一个非空白字符上
$ (shitf+4) / 功能键END    移动到行尾

n$  移动到下面n行的行尾

(n)w   向后移动1(n)个单词,光标停在单词首部,如果已到行尾,则转至下一行行首。

(n)b  向前移动1(n)个单词,光标停在单词首部

(n)e   同w,只是光标停在单词尾部

(n)ge   同b,只是光标停在单词尾部

(n)fx  找到当前行,光标后的第1(n)个为x的字符

(n)F  同f,只不过是反向查找。

Ctrl + e  向下滚动一行

Ctrl + y  向上滚动一行

Ctrl + d  向下滚动半屏

Ctrl + u  向上滚动半屏

Ctrl + f   向下滚动一屏

Ctrl + b  向上滚动一屏

3、复制、剪切和粘贴

yiw  复制(yank)当前单词

yw  复制从当前光标的位置到下一个单词的开头

yb  复制从当前光标的位置到上一个单词的末尾

yy  复制整行(包括换行符)

4yy  复制4行(包括换行符)

y$  复制从当前光标的位置到行尾


(n)x  剪切光标处连续的1(n)个字符

(n)X  剪切当前字符的前1(n)个字符

(n)dl 剪切后1(n)个字符,dl=x

(n)dh  剪切前1(n)个字符,dh=X

(n)d  剪切当前行开始的1(n)行,通常还需要再回车一次

(n)dd  剪切当前1(n)行

(n)dj  剪切上1(n)行

(n)dk  剪切下1(n)行

(n)d$  剪切1(n)行当前字符之后的所有字符

(n)d^  剪切从光标到当前1(n)行的开头

(n)D  剪切当前字符至行尾,D=d$

dG  从光标删除到文件尾 (d 是删除行, G 是文件尾, 连起来就是从光标行删除到文件尾)

:beg,nd  剪切beg至n行(最后的d是指令部分)

:beg,$d  剪切beg行至以后所有的行


p  小写,粘贴在光标之后
P  大写,粘贴在光标之前

4、替换操作

substitute命令,将指定字符串替换为目标字符串。通常我们一般一般使用的是命令的缩写形式:s,具体使用格式如下:

:[range] s/search/replace/[flags] [count]

如果我们想要将所有出现的字符都替换成给定字符,可以在命令中使用g(global)标记,例如

:s/from/to/g

如果没有在命令中指定范围,那么默认范围是当前行。范围指定的用法示例如下:

# 在第10行知第20行每行前面加四个空格
:10,20 s/^/ /g  # 把当前行中的I替换为We。命令中的i标记,是用于指定区分大小写的。
:s/I/We/gi# 将文中所有的字符串idiots替换成managers
:1,$s/idiots/manages/g#通常我们会在命令中使用%指代整个文件做为替换范围
:%s/search/replace/g# 在第5至第15行间进行替换
:5,15s/dog/cat/g# 只在当前行在内的以下4行内进行替换
:s/helo/hello/g4# 只在当前行至文件结尾间进行替换
:.,$s/dog/cat/g# 只在后续9行内进行替换
:.,.+8s/dog/cat/g
  • 参考:VIM学习笔记 替换(Substitute) - 知乎 (zhihu.com)

s/old/new/  用old替换new,替换当前行的第一个匹配

s/old/new/g  用old替换new,替换当前行的所有匹配

%s/old/new/  用old替换new,替换所有行的第一个匹配

%s/old/new/g  用old替换new,替换整个文件的所有匹配

(n)ra  光标之后的1(n)个字符替换为a(r是命令,a是具体的字符)
R  从光标所在处开始替换字符,按 esc 键结束。也就是replace模

(n)~  也就是shift+`(Esc下面),将从光标位置之后的1(n)个字符转换大小写

5、文件操作

:w  保存不退出

:q  不保存退出

:wq  保存退出

:q!  强制不保存退出,不保存数据

:wq!  强制保存退出

:open file  在新窗口中打开文件

:split file  切换到下一个文件

:bn  切换到上一个文件

:bp  切换到上一个文件

6、多窗口操作

在底行模式下可以以多窗口的方式打开一个新文件,具体操作形式如下

:sp file    以纵向显示的方式打开file文件

:vsp file  以横向向显示的方式打开file文件

:vs file    以横向显示的方式打开file文件

在多窗口模式的常用操作如下

命令关键词联想功能
Ctrl w wwindow切换到下一个窗口。
Ctrl w h/←window切换到左边的窗口。
Ctrl w j/↓window切换到下边的窗口。
Ctrl w k/↑window切换到上边的窗口。
Ctrl w l/→window切换到右边的窗口。
Ctrl w rreverse互换窗口。
Ctrl w cclose关闭当前窗口。(但是不能关闭最后一个窗口)
Ctrl w qquit退出当前窗口。(如果是最后一个窗口,则关闭vim编辑器)
Ctrl w oother关闭其他窗口

7、常用的set命令

:set number				" 显示行号
:set nu			        " 显示行号
:set nonumber			" 关闭行号:set showcmd            " 显示输入的命令
:set noshowcmd          " 不显示输入的命令:set tabstop=4 			" 设置 tab space 为4个空格
:set ts=4				" 同 tabstop
:set expandtab			" 将tab替换为指定数量的空格
:set autoindent			" 设置为自动缩进:set background=dark		" 设置背景颜色
:set guifont=consolas:h14		" 设置字体为 consolas,字号为14:set history=700		" 设置保存命令的行数:set autoread		" 设置当文件变化时,自动读取新文件:set wrap		" 启动折行
:set nowrap		" 禁止折行" 切换文件格式,ff是 fileformat 的缩写
:set ff=unix			" 将文件切换为 unix 格式,每行以 "\n" 结尾 
:set ff=dos				" 切换为 Windows 格式,每行以 "\r\n" 结尾" 设置编码格式
:set encoding=utf-8			" 设置 vim 展示文本时的编码格式
:set fileencoding=utf-8		" 设置 vim 写入文件时的编码格式:set filetype=html			" 设定文件类型,方便语法高亮:set hlsearch				" 高亮显示搜索结果:set paste					" 设置为 paste 模式,在粘贴前设置该模式,可以避免各种 auto-formating
:set nopaste				" 切换回 normal 模式

其它操作

  1. :! command   在不退出vim的情况下执行command指令
  2. .  重复前一次命令
  3. u  撤销
  4. ctrl + r  反撤销
  5. 一个小技巧:vim退出时的光标在哪,进去时的光标就在哪

插件和配置

.vimrc文件

vim通常是用.vimrc文件配置的,其实原理很简单,就是.vimrc文件会在进入vim之前执行.vimrc文件中的所有指令,所以我们通常把一些set命令放入到.vimrc文件中,这样就不用每次进入vim时手动的输入指令来个性化我们的vim了。

插件

首先我们需要知道,如果想要很好的使用vim中的插件,一个很重要的工具就是插件管理器,一般来说,最常使用的插件管理器就是vim-plug。不过由于vim的插件种类繁多,没有办法让我们快速上手,所以我们可以尝试去GitHub上找一个一键部署的,比如:GitHub - askunix/VimForCpp: VIM一键配置C/C++开发环境,可自动下载各类插件。VIM一键配置C/C++开发环境,可自动下载各类插件。. Contribute to askunix/VimForCpp development by creating an account on GitHub.icon-default.png?t=N7T8https://github.com/askunix/VimForCpp

如果要手动安装插件的话,可以参考这篇博客:神级编辑器 Vim 使用 - 插件篇 | 闪耀旅途 (hanleylee.com)icon-default.png?t=N7T8https://www.hanleylee.com/articles/usage-of-vim-editor-plugin/

gcc/g++

前置知识:源文件形成可执行文件需要经过预处理、编译、汇编和链接这四大过程。不知道的可以看这篇博客:浅析编译和链接


概念理解

gcc 与 g++ 分别是 gnu 的 c & c++ 编译器 gcc/g++ 在执行编译工作的时候,总共需要4步:

1、预处理,生成 .i 的文件[预处理器cpp]

2、将预处理后的文件转换成汇编语言, 生成文件 .s [编译器egcs]

3、有汇编变为目标代码(机器代码)生成 .o 的文件[汇编器as]

4、连接目标代码, 生成可执行程序 [链接器ld]

参数说明

g++和gcc的使用参数是一样的,所以虽然以gcc的角度进行讲解,但g++也是同样使用的。gcc的多样性大多是源于它的参数,其中有5个比较常用的参数:Esco和std,下面是相关解释:

-E 只运行 C 预编译器,把源文件编译为.i文件。

-S 只激活预处理和编译,把文件编译成为汇编代码.s文件。

-c  只编译生成.o可重定位目标文件。

-o FILE 生成指定的输出文件FILE,也就是说,-o后面是必须跟文件名的。

-std=Standard  用于指定编译器的执行标准,比如C99或者C++11就需要手动指定。

当然,还有一个 -g 选项也是比较常用的,这是在需要调试代码时常用的一个选项。

gcc/g++ 命令的常用选项

-ansi 只支持ANSI标准的C语法。这一选项将禁止GNU C的某些特色,例如asm或typeof关键词。
-c  只编译生成.o可重定位目标文件。
-DMACRO 以字符串"1"定义 MACRO 宏。
-DMACRO=DEFN    以字符串"DEFN"定义 MACRO 宏。
-E  只运行 C 预编译器,把源文件编译为.i文件。
-g  生成调试信息。GNU 调试器可利用该信息。
-IDIRECTORY 指定额外的头文件搜索路径DIRECTORY。
-LDIRECTORY 指定额外的函数库搜索路径DIRECTORY。
-lLIBRARY   连接时搜索指定的函数库LIBRARY。
-m486   针对 486 进行代码优化。
-o FILE 生成指定的输出文件。用在生成可执行文件时。
-O0 不进行优化处理。
-O 或 -O1    优化生成代码。
-O2 进一步优化。
-O3 比 -O2 更进一步优化,包括 inline 函数。
-S 只激活预处理和编译,把文件编译成为汇编代码.s文件。
-static 将禁止使用动态库,即只使用静态库。
-std=Standard  用于指定编译器的执行标准,比如C99或者C++11就需要手动指定。
-share 尽量使用动态库。
-shared 生成共享目标文件。通常用在建立共享库时。
-UMACRO 取消对 MACRO 宏的定义。
-w  不生成任何警告信息。
-Wall   生成所有警告信息。

gdb

使用过VS的人都知道,在VS中编译一个程序时有debug和release版本。而在Linux中的gcc下,默认生成的就是release版本的,也就是说gcc/g++默认生成的可执行程序是没有调试信息的,当然也就不能调试,如果想要生成可调式的,需要在gcc/g++的选项上再加一个-g。如果没有-g选项生成的可执行文件是没有调试信息的,那么就会显示:

由于gdb的使用非常的复杂,东西很多,所以这里我们只是简单的介绍如何快速上手用起gdb,至于详细的内容,可以参考gdb手册:Help (Debugging with GDB) (sourceware.org)icon-default.png?t=N7T8https://sourceware.org/gdb/onlinedocs/gdb/Help.html#index-GDB-version-number

当然,由于这个手册是纯英文的,所以可能很难入手,如果很介意英文,可以尝试在下面这篇博客里找,里面的内容相对来说也是比较全面的:

显示gdb版本信息 | 100个gdb小技巧 (gitbooks.io)icon-default.png?t=N7T8https://wizardforcel.gitbooks.io/100-gdb-tips/content/show-version.html


下面是一些基础常用的gdb命令介绍,以便我们能够快速上手。

  1. list(l) :显示文件的源代码,从当前函数开始,每次显示10行,按回车键继续。其中,list是全称,l是简写。
  2. list(l)  line显示文件源代码,从第line行开始。其余内容同上。
  3. list(l)  func显示文件源代码,从func函数开始。其余内容同上。
  4. run(r):运行程序,通常配合断点来使用。和VS中不同的是,gdb运行程序结束之后,只要gdb没有退出,就还可以继续用的。其中run是全称,r是简写。
  5. start:start和run的功能基本上一致。最大区别的就是:run命令是在第一个断点处停下,start是在main函数的的入口处停下。
  6. break(b) line:在第line行设置断点。
  7. break(b) func:在func的函数入口处设置断点。
  8. break(b) file:line:给file文件的line行打断点。
  9. break(b) file:func:给file文件的func函数入口处打断点。
  10. info break(b):查看所有断点的信息。从gdb的打开到gdb的退出,这之间断点的编号会一直增加,即使某个断点被删除了它的编号也不会被占用。当gdb退出时,所有的断点就会被全部清除。
  11. info break(b) n:查看指定编号为n的断点。
  12. next(n):单条执行,不会进入到语句的函数中,相当于VS中的逐过程执行(F10)。通常在程序运行时配合断点使用。
  13. step(s):和next功能类似,只是step会进入到当前语句的函数中,更详细。相当于VS的逐语句执行(F11)。通常在程序运行时配合断点使用。
  14. continue(c):直接跳转到下一个断点处,没有断点则直接执行至程序结束。
  15. until line:无视任何条件,直接跳转至line行。
  16. finish:略过所有断点,直接执行剩下的所有语句,正常的结束当前函数。
  17. return:立即结束(停止)执行当前函数,并指函数的定返回值
  18. delete breakpoints(d):删除所有断点。
  19. delete breakpoints(d) n:删除编号为n的断点。
  20. disable breakpoints(disable):禁用所有断点。
  21. disable breakpoints(disable) n:禁用编号为n的断点。
  22. enable breakpoints(enable):启用所有断点。
  23. enable breakpoints(enable) n:启用编号为n的断点。
  24. p val:打印一次val变量的值,但只显示一次。
  25. display val:跟踪变量val。每次输入命令之后,都会紧接着显示变量val的值。
  26. info display:显示所有跟踪变量的信息。
  27. undisplay:取消对所有变量的跟踪。
  28. undisplay n:取消对编号为n的变量的跟踪。
  29. disable display <n>:禁用对所有(编号为n)的变量跟踪。
  30. set variable/var val = x:将变量val的值改为x,一般用于特殊情况的测试,不过有一定的风险性,而且一般不常用。
  31. breaktrace(bt):查看各级函数调用及参数,可以类比VS中的查看调用栈帧。
  32. quit(q):退出gdb

其它

  1. 有时我们打开gdb时会显示一些提示信息,感觉很冗余,如果想要不显示,可以在使用gdb时加上一个 -q 参数
  2. 如果不输入任何东西直接回车,默认是执行上一次的命令

make / makefile

作用介绍及语法格式

一般情况下。如果只用gcc/g++编译源文件的话,会很麻烦。首先,重复性的输入近乎相同的指令是一个很繁杂的工作,而且还会有一定的出错概率。其次如果文件很多,很大的话,那么对应的工作量也是会非常大的。所以综合考虑就比较适合使用make和Makefile用于日常开发。下面就让我们简单的快速了解一下make和Makefile,以快速上手。

首先,make是一个指令,Makefile是一个文件。Makefile是我们自己手动创建并写入的,而且文件名必须为makefile、Makefile或者GNUmakefile,只能是这三个之一,其中前两个是最为常用的。原因如下:

默认的情况下,make命令会在当前目录下按顺序找寻文件名为“GNUmakefile”、“makefile”、“Makefile”的文件。在这三个文件名中,最好使用“Makefile”这个文件名,因为,这个文件名第一个字符为大写,这样有一种显目的感觉。最好不要用 “GNUmakefile”,这个文件是GNU的make识别的。有另外一些make只对全小写的“makefile”文件名敏感,但是基本上来说,大多数的make都支持“makefile”和“Makefile”这两种默认文件名。

make命令就是执行Makefile文件中的内容,make命令的用法格式如下:

make #执行第一条方法
make target #执行具体的target方法#用法说明:
# target是对应Makefile文件中的方法名
# 当没有指定具体的方法名时,默认执行第一条方法

其中make命令有3个较为常用的参数:

1)-k :使用 -k 参数可以让 make 命令在发现错误时仍然继续执行,而不是在检测到第一个错误时就停下来。利用这个选项可以在一次操作中发现所有未编译成功的源文件

2)-n :使用 -n 参数,让 make 命令输出将要执行的操作步骤,而不是真正执行这些操作;

3)-f :使用 -f 参数,后面可以接一个文件名,用于指定一个文件作为 makefile 文件。如果没有使用 -f 选项,则 make 命令会在当前目录下查找名为 makefile 的文件,如果该文件不存在,则查找名为 Makefile 的文件。 


从宏观概念上讲,Makefile里主要包含了五个东西:

显式规则、隐晦规则、变量定义、文件指示和注释

  1. 显式规则:显式规则说明了,如何生成一个或多的的目标文件。这是由Makefile的书写者明显指出,要生成的文件,文件的依赖文件,生成的命令。
  2. 隐晦规则:由于我们的make有自动推导的功能,所以隐晦的规则可以让我们比较粗糙地简略地书写Makefile,这是由make所支持的。
  3. 变量的定义:在Makefile中我们要定义一系列的变量,变量一般都是字符串,这个有点你C语言中的宏,当Makefile被执行时,其中的变量都会被扩展到相应的引用位置上。
  4. 文件指示:其包括了三个部分,一个是在一个Makefile中引用另一个Makefile,就像C语言中的include一样;另一个是指根据某些情况指定Makefile中的有效部分,就像C语言中的预编译#if一样;还有就是定义一个多行的命令。
  5. 注释:Makefile中只有行注释,和UNIX的Shell脚本一样,其注释是用“#”字符,这个就像C/C++中的“//”一样。如果你要在你的Makefile中使用“#”字符,可以用反斜框进行转义,如:“\#”。

而从使用层面上讲,makefile文件有着固定的语法格式,由一系列的“方法”组成,而每一个“方法”都由依赖关系和依赖方法两部分组成,“方法”的语法可以概括为如下格式:

target:prerequisites
<tab>command1
<tab>command2
...#格式说明:
# 注释是以#号开头,一直延续到该行的结束。
# target是方法的名称,一般就是编译器生成的文件名(当然也可以不是)
# prerequisites通常是依赖关系,就是下面的命令会用到哪些文件
# command就是具体的依赖方法,也就是make需要执行的命令,它可以是任意的shell命令
# 一个强制性的规则是,每一条依赖方法前必须有一个制表符<tab>
# 续行符反斜杠'\'以让所有的命令在逻辑上处于同一行

 .PHONY伪目标

有一种特殊的方法叫做伪目标,伪目标用.PHONY来定义,伪目标的格式:

.PHONY:name# .PHONY:是声明,后面的name是具体的伪目标方法名

伪目标的作用:

  1. 伪目标并不是实际存在的,所以可以避免命令与目录下的文件名重复。
  2. 伪目标可以没有依赖关系,也就是说可以直接拿来用。
  3. 伪目标可以保证依赖方法总是被执行的。
  4. .PHONY,伪目标。凡是被.PHONY的,依赖方法总是被执行,就不会有“make不会执行没有修改过的文件”的效果。

make的自动推导功能

make很强大,它可以自动推导文件以及文件依赖关系后面的命令。而且如果当前语句中出现了一个未定义的依赖关系,make是会继续查看后面的内容的,并顺便寻找这个未定义的依赖关系。

所以我们就没必要去在每一个[.o]文件后都写上类似的命令,因为,我们的make会自动识别,并自己推导命令。只要make看到一个[.o]文件,它就会自动的把[.c]文件加在依赖关系中,如果make找到一个whatever.o,那么 whatever.c,就会是whatever.o的依赖文件。并且 cc -c whatever.c 也会被推导出来,于是,我们的makefile 再也不用写得这么复杂。例如:

objects = main.o kbd.o 
cc = gccedit : $(objects)$(cc) -o $@ $^
%.o:%.c  #这是Makefile的静态模式规则,意思是:所有的.o文件,依赖于对应的.c文件.PHONY : clean
clean :rm edit $(objects)

不会执行未改动的依赖方法

如果生成文件和方法名target是一样的话,那么make就不会执行没有修改过的文件对应的方法。大致原理就是通过对比方法名target和依赖关系文件的时间戳来实现的。但是如果生成的文件和方法名target不一致的话,就不会有此效果。所以大多数情况下,为了防止大规模程序的多余编译行为,我们一般默认就是把生成的文件名和方法名target保持一致。


两个特殊字符: - 和 @:

1)若在依赖关系的语句前,加上了符号 '-',则表明将忽略该命令产生的所有错误

2)若在依赖关系的语句前,加上了符号 '@',则表明不会将该命令显示在标准输出上


宏 /变量

宏,也可以理解为变量,定义的方法很简单,格式如下:

NAME=value# NAME是宏名(变量名),val是对应的值
# 这个值常用于为了简化写法而设置为依赖关系的文件名、生成的文件名、使用的编译器等名称

引用宏的方法是用$坐前缀,然后将宏名用小括号或者大括号引起来,格式如下:

# 两种写法都可以
$(NAME) ${NAME} 

使用宏定义,可以让 makefile 文件的可移植性更强。除了自己定义一些宏以外,make 命令还内置了一些特殊的宏定义,使得 makefile 文件变得更加简洁:

         宏          说明
$?当前目标所依赖的文件列表中比当前目标文件还要新的文件
$@当前目标的名字
$<当前依赖文件的名字
$*不包括后缀名的当前依赖文件的名字

除了在 makefile 文件里面定义宏以外,还可以调用 make 命令时,在命令行上给出宏定义。命令行上的宏定义将覆盖在 makefile 文件中的宏定义。需要注意的是,在 make 命令后接宏定义时,宏定义必须以单个参数的形式传递,因此,尽量要避免在宏定义中使用空格或加引号。 

相关文章:

快速上手Linux基础开发工具

目录 软件包管理器 概念理解 用法示例 - 以yum为例 vim 模式的切换 常用操作 插件和配置 gcc/g gdb make / makefile 软件包管理器 概念理解 在Linux下安装软件的话&#xff0c;一个比较原始的办法是下载程序的源代码&#xff0c;然后进行编译&#xff0c;进而得到…...

【开发工具】idea 的全局搜索快捷键(Ctrl+shift+F)失效

文章目录 前言1. 取消 输入法的快捷键&#xff08;推荐使用&#xff09;2.更改 idea的快捷键3. 热键占用总结 前言 当你发现在idea 中看到用于全局搜索的快捷键就是 CtrlshiftF&#xff0c;可是怎么按都不管用的时候&#xff0c;你就不要再执着于自己的操作继续狂点电脑按键了…...

港联证券:“火箭蛋”来袭 蛋价涨势能否延续?

上个交易周&#xff08;9月11日至15日&#xff09;&#xff0c;鸡蛋期货商场呈现了意想不到的涨势。9月15日&#xff0c;鸡蛋期货多个合约大涨&#xff0c;其中2310合约涨超5.6%&#xff0c;主力合约2311盘中两度触及涨停&#xff0c;最终收涨6%。业内人士以为&#xff0c;鸡蛋…...

Vue3_vite

使用Vue-cli创建 使用vite创建 Composition API 组合API setup 1.Vue3中的一个新的配置项,值为一个函数 2.可以将组件中所用到的数据,方法等配置在setup中. 3.setup函数的两种返回值 3.1若返回一个对象,则对象中的属性,方法,在模板中均可以直接使用. 3.2若返回一个渲染函数…...

python-字符串去掉空格的常见方法

python提供了去掉字符串空格的方法&#xff0c;可以满足大部分需求。 但在实际应用中&#xff0c;还需要灵活借助python其他方法&#xff0c;来实现字符串空格的删除。 比如&#xff0c;去掉字符串的全部空格、字符串连续空格保留一个等&#xff0c;都需要结合其他的方法来实现…...

如何写出一个成熟的线上线下结合的营销方案?

分享一下咱们案例库里策划的一个线上线下结合的活动的案例。 这个活动是为了推广一个新品牌&#xff0c;增加品牌知名度和用户粘性。 你可以根据以下几个要点来进行活动策划&#xff1a; 1、目标&#xff1a; 让目标用户了解并喜欢新品牌&#xff0c;激发用户参与和分享&am…...

Vc - Qt - “扩张“的窗口

该示例演示了一个"扩张的窗口"&#xff0c;主窗口的布局为水平布局&#xff0c;内置两个子窗口&#xff0c;采用定时器设置左边窗口的宽度&#xff0c;达到控制"扩张"的目的。 #include <QApplication> #include <QWidget> #include <QHBox…...

vue学习-02vue入门之组件

删除Vue-cli预设 在用户根目录下(C:\Users\你的用户名)这个地址里有一个.vuerc 文件,修改或删除配置 组件 Props(组件之间的数据传递) Prop 的大小写 (camelCase vs kebab-case)不敏感Prop 类型: String Number Boolean Array Object Date Function Symbol传递静态或动态 Pr…...

解决Pycharm使用Conda激活环境失败的问题

Q:公司电脑终端使用powershell来激活conda环境时报错? 同时手动打开powershell报"profile.ps1” 无法被加载的错误 A: 1,手动打开powershell&#xff0c;设置管理员打开 2,打开powershell 打开 PowerShell 终端&#xff0c;并输入以下命令&#xff1a;Get-ExecutionPo…...

SpringSecurity 核心组件

文章目录 SpringSecurity 结构组件&#xff1a;SecurityContextHolder组件&#xff1a;Authentication组件&#xff1a;UserDetailsService组件&#xff1a;GrantedAuthority组件总结 SpringSecurity 结构 在SpringSecurity中的jar分为4个&#xff0c;作用分别为 jar作用spri…...

【Vue】快速入门和生命周期

目录 前言 一、vue的介绍 1. Vue.js是什么&#xff1f; 2. 库和框架的区别 3.基本概念和用法&#xff1a; 二、MVVM的介绍 1. 什么是MVVM&#xff1f; 2. MVVM的组成部分 3. MVVM的工作流程 4. MVVM的优势 5. MVVM的应用场景 三、vue实例 1.模板语法&#xff1a; …...

JVM架构和内存管理优化

Java虚拟机&#xff08;JVM&#xff09;是Java编程语言的核心组件&#xff0c;负责执行Java字节码并提供运行时环境&#xff0c;使得Java程序可以在不同的平台上运行。了解JVM的工作原理和内存管理对于优化代码性能和理解Java的内存管理和垃圾收集机制非常重要。在本文中&#…...

C语言——贪吃蛇小游戏

目录 一、ncurse 1.1 为什么需要用ncurse&#xff1a; 1.2 ncurse的输入输出&#xff1a; 1.2.1 如何使用ncurse&#xff1a; 1.2.2 编译ncurse的程序&#xff1a; 1.2.3 测试输入一个按键ncurse的响应速度&#xff1a; 1.3 ncurse上下左右键获取&#xff1a; 1.3.1 如…...

PHP8中获取并删除数组中第一个元素-PHP8知识详解

我在上一节关于数组的教程&#xff0c;讲的是在php8中获取并删除数组中最后一个元素&#xff0c;今天分享的是相反的&#xff1a;PHP8中获取并删除数组中第一个元素。 回顾一下昨天的知识&#xff0c;array_pop()函数将返回数组的最后一个元素&#xff0c;今天学习的是使用arr…...

EtherCAT 总线型 4 轴电机控制卡解决方案

 技术特点  支持标准 100M/s 带宽全双工 EtherCAT 总线网络接口及 CoE 通信协议一 进一出&#xff08;RJ45 接口&#xff09;&#xff0c;支持多组动态 PDO 分组和对象字典的自动映射&#xff0c;支持站 号 ID 的自动设置与保存&#xff0c;支持 SDO 的电机参数设置与…...

Upload-labs十六和十七关

目录 第十六关第十七关 第十六关 直接上传php文件判断限制方式&#xff1a; 同第十五关白名单限制 第十六关源码&#xff1a; 代码逻辑判断了后缀名、content-type&#xff0c;以及利用imagecreatefromgif判断是否为gif图片&#xff0c;最后再做了一次二次渲染 第71行检测…...

软件包的管理

概念 在早期Linux系统中&#xff0c;要想在Linux系统中安装软件只能采取编译源码包的方式进行安装&#xff0c;所以早期安装软件是一件非常困难、耗费耐心的事情&#xff0c;而且大多数服务程序仅提供源代码&#xff0c;还需要运维人员编译后自行解决软件之间的依赖关系。所以…...

常见入门级进销存系统合集

进销存系统是企业管理中不可或缺的一环&#xff0c;它们可以帮助企业有效管理库存、销售和采购等关键业务。然而&#xff0c;对于初创企业和小型企业来说&#xff0c;选择一个合适的进销存系统可能是一项挑战。在这篇文章中&#xff0c;我们将探讨入门级和资深级进销存系统之间…...

爬虫逆向实战(32)-某号店登录(RSA、补环境、混淆)

一、数据接口分析 主页地址&#xff1a;某号店 1、抓包 通过抓包可以发现登录接口是/publicPassport/login.do 2、判断是否有加密参数 请求参数是否加密&#xff1f; 通过查看“载荷”模块可以发现&#xff0c;有三个加密参数&#xff1a;username、password、captchaTok…...

正则表达式学习和高级用法

以下所有的验证都在 在线验证 1. 起始符 / 正则表达式的起始符2. 限定符 匹配前面的子表达式**1次或多次**。例如&#xff0c;zo 能匹配 "zo" 以及"zoo"&#xff0c;但不能匹配 "z"。等价于 {1,}。 ? 匹配前面的子表达式**0次或1次**。例如…...

C# Onnx Yolov8 Fire Detect 火焰识别,火灾检测

效果 项目 代码 using Microsoft.ML.OnnxRuntime.Tensors; using Microsoft.ML.OnnxRuntime; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using Syste…...

线程安全问题

目录 一、线程安全 二、线程安全问题 三、线程安全 1.同步代码块 2.同步方法 3.Lock锁 3.1常用方法&#xff1a; 3.2 死锁 3.3 练习&#xff1a; 四、生产者和消费者&#xff08;线程通信问题&#xff09; 一、线程安全 如果有多个线程在同时运行&#xff0c;而这些…...

【力扣每日一题】2023.9.18 打家劫舍Ⅲ

目录 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 代码&#xff1a; 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 今天是打家劫舍3&#xff0c;明天估计就是打家劫舍4了。 今天的打家劫舍不太一样&#xff0c;改成二叉树了&#xff0c;不过规则没有变&…...

Docker基础学习

Docker 学习目标&#xff1a; 掌握Docker基础知识&#xff0c;能够理解Docker镜像与容器的概念 完成Docker安装与启动 掌握Docker镜像与容器相关命令 掌握Tomcat Nginx 等软件的常用应用的安装 掌握docker迁移与备份相关命令 能够运用Dockerfile编写创建容器的脚本 能够…...

esbuild中文文档-路径解析配置项(Path resolution - Alias、Conditions)

文章目录 路径解析配置项 Path resolution别名 Alias条件解析 Conditionsconditions是如何工作的 结语 哈喽&#xff0c;大家好&#xff01;我是「励志前端小黑哥」&#xff0c;我带着最新发布的文章又来了&#xff01; 老规矩&#xff0c;小手动起来~点赞关注不迷路&#xff0…...

您的应用存在隐藏最近任务列表名称的行为,不符合华为应用市场审核标准

最近各家应用市场&#xff0c;唯独华为审核被拒了。。理由是您的应用存在隐藏最近任务列表名称的行为&#xff0c;不符合华为应用市场审核标准。 根据华为给出的视频&#xff0c;app在任务队列&#xff08;也就是俗称的安卓多任务管理后台&#xff09;不显示应用名。因为我们ap…...

Spring的 webFlux 和 webMVC

看到一个测评文章&#xff0c;并发在300的时候webMVC 和 webFlux的处理能力不相上下&#xff0c; 当并发达到3000的时候, webFlux明显优于webMVC, 有图有真相&#xff0c; 我信了. webMVC 是 one-request-one thread 堵塞模式, flux是非阻塞模式&#xff0c; 是spring家族系列…...

【洛谷算法题】P5706-再分肥宅水【入门1顺序结构】

&#x1f468;‍&#x1f4bb;博客主页&#xff1a;花无缺 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 花无缺 原创 收录于专栏 【洛谷算法题】 文章目录 【洛谷算法题】P5706-再分肥宅水【入门1顺序结构】&#x1f30f;题目描述&#x1f30f;输入格式…...

android studio环境搭建让你的开发之旅更加简单

示例示例Android Studio环境搭建&#xff1a;下载并安装Android Studio&#xff1a;从官网下载Android Studio&#xff0c;然后双击安装文件&#xff0c;按照提示进行安装&#xff0c;安装完成之后&#xff0c;可以在桌面上找到Android Studio的快捷方式。 Android Studio环境…...

Java面试_并发编程_线程基础

Java面试_并发编程_线程基础 线程基础线程和进程的区别(出现频率: 3⭐)并行和并发的区别(出现频率: 2⭐)线程的创建(出现频率: 4⭐)线程的状态(出现频率: 4⭐)让线程按顺序执行(出现频率: 3⭐)notify()和notifyAll()有什么区别(出现频率: 2⭐)wait方法和sleep方法的区别(出现频…...

教做衣服的网站/抖音代运营收费详细价格

使用的库文件为Newtonsoft.Json 读取JSON文件 /// <summary>/// 读取JSON文件/// </summary>/// <param name"key">JSON文件中的key值</param>/// <returns>JSON文件中的value值</returns>public JObject Readjson(string json…...

没有自己的网站做百度竞价/怎么优化标题和关键词排名

右键要查询的文件 -- team -- show local history 显示 修改历史窗口 选择修改历史中一条记录 -- 右键 --Compare current with local 显示文件对比 转载于:https://www.cnblogs.com/caer/p/5729011.html...

电子商务网站用户协议/合肥seo网络营销推广

(点击上方快速关注并设置为星标&#xff0c;一起学Python)来源&#xff1a;李英杰同学 链接&#xff1a;https://www.cnblogs.com/injet/p/9825050.html用 Python 关机你肯定听过或者实践过&#xff0c;那么用 Python 开机呢&#xff1f;这是一个神奇的方法&#xff0c;教你如…...

做pc端网站平台/百度seo优化是做什么的

成熟又有钱的是父亲&#xff0c;成熟又没钱的是舅舅&#xff0c;不成熟有没钱的是儿子&#xff0c;看来自己只能做个儿子了。...

国际网站怎么注册免费的/谷歌浏览器安卓版

接着上一篇在同一台服务器上配置app1.domain.com和app2.domain.com多个web应用&#xff0c;这里记录下在nginx下给express web app配置静态代理和文件压缩。目的 为了减少node.js对静态文件的处理和加快前端下载静态资源的速度&#xff0c;决定使用nginx做静态代理&#xff0c;…...

做 理财网站/seo主要优化

1&#xff1a; 常量 Java finanal PHP const 2 数据的定义&#xff1a; 声明数组 数据类型[ ] 数组名 或者 数据类型 数组名[ ]&#xff1b; int[] scores ;或者 int scores[]; 分配空间 数组名 new 数据类型 [ 数组长度 ]; scores new int[5] 我们也可以将上…...