【Linux】Linux开发工具-vim / 编译器-gcc/g++ / 调试器-gdb / git操作 / 项目自动化构建工具-make/Makefile

news2024/11/28 22:53:25

主页:醋溜马桶圈-CSDN博客

专栏:Linux_醋溜马桶圈的博客-CSDN博客

giteemnxcc (mnxcc) - Gitee.com

目录

1.在Linux写自己的第一个程序

1.1 nano指令

1.2 nano指令的使用

1.2.1 介绍

1.2.2 演示

1.2.2.1 创建.c文件

1.2.2.2 nano code.c

1.2.2.3 gcc code.c

1.2.2.4 ./a.out

2.Linux开发工具 - vim

2.2 Linux编辑器-vim使用

2.3 vim的基本概念

2.3.1 正常/普通/命令模式(Normal mode)

2.3.2 插入模式(Insert mode)

2.3.3 末行模式(last line mode)

2.4 vim的基本操作 

2.5 vim正常模式命令集

2.5.1 插入模式

2.5.2 命令模式

2.5.3 移动光标

2.5.4 删除文字

2.5.5 复制

2.5.6 替换

2.5.7 撤销上一次操作

2.5.8 更改

2.5.9 跳至指定的行

2.6 vim中批量化注释 

2.6.1 批量化注释

2.6.2 批量化删除注释

2.7 vim配置

3.Linux编译器-gcc/g++

3.1 背景知识

3.2 gcc如何完成

3.2.1 预处理(进行宏替换)

3.2.2 编译(生成汇编)

3.2.3 汇编(生成机器可识别代码)

3.2.4 链接(生成可执行文件或库文件)

3.2.5 函数库

3.3 gcc选项

gcc-o

3.4 g++

c++的文件后缀

3.5 程序的翻译过程

3.5.1 预处理阶段

gcc -E 

头文件展开

条件编译

gcc -D 动态添加宏

3.5.2 编译阶段

gcc -S

3.5.3 汇编阶段

gcc -c

3.5.4 链接阶段

是什么? 

函数库

为什么?

怎么办?

动态链接

静态链接

4.Linux调试器-gdb

4.1 背景

4.2 开始使用

1. list

2. run(运行)

3. break(断点)

4. info break(断点信息)

5. delete breakpoints(n)(删除断点)

6. disable breakpoints(禁用断点)

7. enable breakpoints(启用断点)

8. n 或 next:单条执行(逐过程)

9. s或step:进入函数调用(逐语句)

10. p 变量:打印变量值

11. display 变量名:跟踪查看一个变量

12. undisplay:取消对先前设置的变量的跟踪

13. until X行号:跳至X行

4.3 理解

5.git操作 - gitee

5.1 使用 git 命令行

5.2 使用gitee

5.2.1 注册账户

5.2.2 新建仓库

5.3 Linux-git操作

5.3.1 git三板斧

git add

git commit

git push

5.3.2 git删除操作

5.3.3 git日志

5.3.4 图示git

6.Linux项目自动化构建工具-make/Makefile

6.1 背景

6.2 实例代码

6.3 理解

6.4 原理

6.4.1 依赖关系

6.4.2 依赖方法

6.4.3 项目清理


1.在Linux写自己的第一个程序

1.1 nano指令

我们在Windows中有很多的编译环境,大家应该都很熟悉,但是在Linux中,我们怎么写代码呢?

这里,我介绍一个非常简单的指令->nano

这个指令就类似于我们Windows中的记事本,使用方法也很简单

1.2 nano指令的使用

1.2.1 介绍

nano指令的使用主要分为五步

  1. 创建.c文件
  2. nano 源文件.c
  3. gcc code.c
  4. ./a.out

1.2.2 演示

具体的流程我们演示一下

1.2.2.1 创建.c文件

先touch一个.c文件,类比于Windows中的创建文本文件

1.2.2.2 nano code.c

nano code.c类比于打开文本文件

然后我们就可以编写代码了

编写完成后选择ctrl+x

保存选择Y,不保存选择N

然后回车即可

1.2.2.3 gcc code.c

编写完成后我们就可以编译了,使用gcc指令

1.2.2.4 ./a.out

编译完成就可以执行程序了,使用./a.out指令

2.Linux开发工具 - vim

2.1 IDE例子

2.2 Linux编辑器-vim使用

vi/vim的区别简单点来说,它们都是多模式编辑器,不同的是vim是vi的升级版本,它不仅兼容vi的所有指令,而且还有一些新的特性在里面。例如语法加亮,可视化操作不仅可以在终端运行,也可以运行于x window、 mac os、windows

2.3 vim的基本概念

本文我们讲解vim的三种模式(其实有好多模式,目前掌握这3种即可),分别是命令模式(command mode)、插入模式(Insert mode)和底行模式(last line mode),各模式的功能区分如下:

2.3.1 正常/普通/命令模式(Normal mode)

控制屏幕光标的移动,字符、字或行的删除,移动复制某区段及进入Insert mode下,或者到 last line mode

2.3.2 插入模式(Insert mode)

只有在Insert mode下,才可以做文字输入,按「ESC」键可回到命令行模式。该模式是我们后面用的最频繁的编辑模式。

2.3.3 末行模式(last line mode)

文件保存或退出,也可以进行文件替换,找字符串,列出行号等操作。 在命令模式下,shift+: 即可进入该模式。要查看你的所有模式:打开vim,底行模式直接输入:help vim-modes

2.4 vim的基本操作 

进入vim,在系统提示符号输入vim及文件名称后,就进入vim全屏幕编辑画面:

[正常模式] 切换至 [插入模式]

  • 输入a
  • 输入i
  • 输入o

[插入模式] 切换至 [正常模式]

  • 目前处于[插入模式],就只能一直输入文字,如果发现输错了字,想用光标键往回移动,将该字删除,可以先按一下「ESC」键转到[正常模式]再删除文字。当然,也可以直接删除。

[正常模式]切换至[末行模式]

  • shift + ;其实就是输入 :

退出vim及保存文件

在[正常模式]下,按一下「:」冒号键进入「Last line mode」,例如:

  • :w (保存当前文件)
  • :wq (输入「wq」,存盘并退出vim)
  • :q! (输入q!,不存盘强制退出vim)

2.5 vim正常模式命令集

2.5.1 插入模式

  • 按「i」切换进入插入模式「insert mode」,按“i”进入插入模式后是从光标当前位置开始输入文件;
  • 按「a」进入插入模式后,是从目前光标所在位置的下一个位置开始输入文字;
  • 按「o」进入插入模式后,是插入新的一行,从行首开始输入文字

2.5.2 命令模式

  • 按「ESC」键

2.5.3 移动光标

vim可以直接用键盘上的光标来上下左右移动,但正规的vim是用小写英文字母「h」、「j」、「k」、「l」,分别控制光标左、下、上、右移一格

  • 按「G」:移动到文章的最后
  • 按「 $ 」:移动到光标所在行的“行尾”
  • 按「^」:移动到光标所在行的“行首”
  • 按「w」:光标跳到下个字的开头
  • 按「e」:光标跳到下个字的字尾
  • 按「b」:光标回到上个字的开头
  • 按「#l」:光标移到该行的第#个位置,如:5l,56l
  • 按[gg]:进入到文本开始
  • 按[shift+g]:进入文本末端
  • 按「ctrl」+「b」:屏幕往“后”移动一页
  • 按「ctrl」+「f」:屏幕往“前”移动一页
  • 按「ctrl」+「u」:屏幕往“后”移动半页
  • 按「ctrl」+「d」:屏幕往“前”移动半页

2.5.4 删除文字

  • 「x」:每按一次,删除光标所在位置的一个字符
  • 「#x」:例如,「6x」表示删除光标所在位置的“后面(包含自己在内)”6个字符
  • 「X」:大写的X,每按一次,删除光标所在位置的“前面”一个字符
  • 「#X」:例如,「20X」表示删除光标所在位置的“前面”20个字符
  • 「dd」:删除光标所在行
  • 「#dd」:从光标所在行开始删除#行

2.5.5 复制

  • 「yw」:将光标所在之处到字尾的字符复制到缓冲区中
  • 「#yw」:复制#个字到缓冲区
  • 「yy」:复制光标所在行到缓冲区
  • 「#yy」:例如,「6yy」表示拷贝从光标所在的该行“往下数”6行文字
  • 「p」:将缓冲区内的字符贴到光标所在位置。注意:所有与“y”有关的复制命令都必须与“p”配合才能完成复制与粘贴功能

2.5.6 替换

  • 「r」:替换光标所在处的字符
  • 「R」:替换光标所到之处的字符,直到按下「ESC」键为止

2.5.7 撤销上一次操作

  • 「u」:如果您误执行一个命令,可以马上按下「u」,回到上一个操作。按多次“u”可以执行多次回复
  • 「ctrl + r」: 撤销的恢复

2.5.8 更改

  • 「cw」:更改光标所在处的字到字尾处
  • 「c#w」:例如,「c3w」表示更改3个字

2.5.9 跳至指定的行

  • 「ctrl」+「g」列出光标所在行的行号
  • 「#G」:例如,「15G」,表示移动光标至文章的第15行行首

2.6 vim中批量化注释 

2.6.1 批量化注释

  1. ctrl+v
  2. hjkl进行区域选择
  3. shift+i=I
  4. “//”
  5. esc*2

2.6.2 批量化删除注释

  1. ctrl+v
  2. hjkl进行区域选择(包含且仅包含“//”-可以用L控制)
  3. d删除

2.7 vim配置

 我们普通用户打开未配置的vim的时候,和Windows中的vs界面差别很大,使用不是很便捷

这里我们可以配置一下vim,便于我们的操作

我们可以在gitee中搜索vimforcpp

VimForCpp: 快速将vim打造成c++ IDE (gitee.com)

curl -sLf https://gitee.com/HGtz2222/VimForCpp/raw/master/install.sh -o ./install.sh && bash ./install.sh

这时打开vim就是这样了:有了简单的图形化页面

3.Linux编译器-gcc/g++

3.1 背景知识

  1. 预处理(进行宏替换)
  2. 编译(生成汇编)
  3. 汇编(生成机器可识别代码)
  4. 连接(生成可执行文件或库文件)

3.2 gcc如何完成

格式 

gcc [选项] 要编译的文件 [选项] [目标文件]

3.2.1 预处理(进行宏替换)

预处理功能主要包括宏定义,文件包含,条件编译,去注释等

  • 预处理指令是以#号开头的代码行

实例: 

gcc –E hello.c –o hello.i
  • 选项“-E”,该选项的作用是让 gcc 在预处理结束后停止编译过程
  • 选项“-o”是指目标文件,“.i”文件为已经过预处理的C原始程序

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.2.5 函数库

在这里涉及到一个重要的概念:函数库

我们的C程序中,并没有定义“printf”的函数实现,且在预编译中包含的“stdio.h”中也只有该函数的声明,而没有定义函数的实现,那么,是在哪里实“printf”函数的呢?

最后的答案是:系统把这些函数实现都被做到名为 libc.so.6 的库文件中去了,在没有特别指定时,gcc 会到系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到 libc.so.6 库函数中去,这样就能实现函数“printf”了,而这也就是链接的作用

函数库一般分为静态库和动态库两种。

  • 静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件了。其后缀名一般为“.a”
  • 动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,这样可以节省系统的开销。动态库一般后缀名为“.so”,如前面所述的 libc.so.6 就是动态库。gcc 在编译时默认使用动态库。完成了链接之后,gcc 就可以生成可执行文件,如下所示
gcc hello.o –o hello

gcc默认生成的二进制程序,是动态链接的,这点可以通过 file 命令验证

3.3 gcc选项

  • -E 只激活预处理,这个不生成文件,你需要把它重定向到一个输出文件里面
  • -S  编译到汇编语言不进行汇编和链接
  • -c  编译到目标代码
  • -o  文件输出到文件
  • -static 此选项对生成的文件采用静态链接
  • -g 生成调试信息。GNU 调试器可利用该信息
  • -shared 此选项将尽量使用动态库,所以生成文件比较小,但是需要系统由动态库.
  • -O0
  • -O1
  • -O2
  • -O3 编译器的优化选项的4个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高
  • -w  不生成任何警告信息
  • -Wall 生成所有警告信息

gcc-o

这样我们就可以编译成指定的文件名称

3.4 g++

gcc不能用来编译c++代码,我们创建一个test.cc,.cc表示是c++代码,但是用gcc编译会报错

所以我们就可以用g++来编译c++文件

g++的选项和gcc的选项一模一样,所以也可以带上选项

使用c++11标准

gcc不能编译c++代码,但是g++可以编译c语言代码

g++也可以加-o选项,编译成指定的可执行程序

c++的文件后缀

c++的文件后缀有三种:.cc  .cpp  .cxx

(Linux不关心文件后缀不代表编译器不关心文件后缀)

3.5 程序的翻译过程

程序的翻译过程分为:预处理、编译、汇编、链接

在Linux中,我们可以用gcc命令的各种选项看到翻译的各过程,可以在每个阶段停下来,并且可以看到中间的翻译结果,这样就更便于我们理解翻译过程

3.5.1 预处理阶段

gcc -E 
gcc -E test.c -o test.i

形成一个test.i文件,文件中保存的是gcc -E产生的临时结果

头文件展开

我们的test.c文件中只有24行,结果test.i中多出800多行,那多出来的这么多是什么呢?

其实这么多代码都是从stdio.h这个头文件展开来的

在预处理阶段,编译器会将我们源代码中所需要的头文件拷贝到源文件中来,我们的头文件中可能也会包含头文件,所以可能会进行递归的拷贝,这个过程叫做头文件展开

在安装编译器的时候,C标准库的头文件一般会一并下载到/usr/include/

我们可以打开stdio.h看一下

对比一下,确实我们展开的是stdio.h

我们可以看到预处理阶段进行了宏替换注释也被替换

条件编译

我们现在下载的软件,大多都分为好几个版本:专业版、社区版、学生版...

那这是怎么维护的呢,如果一个版本有一份源代码,那维护起来的成本是非常大的,这就可以用条件编译来解决这个问题了,只需要维护一份代码,可以用条件编译进行代码的动态裁剪

我们在C语言阶段就有过条件编译的说明:#ifdef #elif #else #endif

具体在《C语言 预处理》专栏的条件编译有说明

C语言 预处理详解-CSDN博客

我们编译成proj.i看一下

我们可以看到,满足条件的保留,不满足条件的删除

gcc -D 动态添加宏

我们可以不在文件中宏定义,可以通过gcc -D进行命令行式的宏定义,这样我们就可以动态地向源代码添加宏

3.5.2 编译阶段

预处理的结果是test.i,是一份干净的C语言代码

gcc -S
gcc -S test.i -o test.s

gcc -S产生一个test.s的临时结果

但是这个代码我们可能看不懂,但是我们知道这是汇编语言

3.5.3 汇编阶段

gcc -c
gcc -c test.s -o test.o

gcc -c 将test.s文件转成test.o文件,.o表示.obj,在vs中我们编译文件就会产生.obj文件

产生的.obj文件叫做目标文件,这个目标文件不能直接执行,最终形成.exe可执行程序才能运行

3.5.4 链接阶段

gcc test.o -o my.exe

只有最终形成可执行文件,才可以执行

关于链接,我们有三个问题:

  • 是什么?
  • 为什么?
  • 怎么办? 
是什么? 

链接的过程是我们的程序和库结合的过程

我们的C程序中,并没有定义“printf”的函数实现,且在预编译中包含的“stdio.h”中也只有该函数的声明,而没有定义函数的实现,那么,是在哪里实“printf”函数的呢?

最后的答案是:系统把这些函数实现都被做到名为 libc.so.6 的库文件中去了,在没有特别指定时,gcc 会到系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到 libc.so.6 库函数中去,这样就能实现函数“printf”了,而这也就是链接的作用

库:语言一定要有自己的标准库

我们可以用ldd命令来看到对应的动态库

这就是我们的C标准库

在安装开发环境的时候,会安装C标准库+C头文件,这时候我们才可以包含对应的头文件,调用头文件里声明的函数

函数库

函数库一般分为静态库和动态库两种

静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件了。其后缀名一般为“.a

动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,这样可以节省系统的开销。动态库一般后缀名为“.so”,如前面所述的 libc.so.6 就是动态库。gcc 在编译时默认使用动态库。

  • Linux中,动态库.so 静态库.a
  • Windows中,动态库.dll 静态库.lib
为什么?
  • 让开发站在巨人的肩膀上
  • 提高开发的效率
怎么办?

链接时,两种链接方式:

  • 动态链接
  • 静态链接

动态链接

动态库和动态链接的优缺点

  1. 不能丢失
  2. 节省资源 
静态链接

静态库和静态链接的优缺点

  1. 一旦形成,和库无关
  2. 浪费资源 

C动态库,是默认提供的

gcc默认形成的可执行程序,默认采用动态链接

而Linux中静态库默认是没有的

安装静态库我们可以用yum指令

sudo yum install -y glibc-static libstdc++-static

这时我们就可以编译通过了

同样运行也能通过

静态链接的应用场景

由于静态链接不依赖于任何的动态库,所以在移植到其他环境中时就不需要做过多的环境检测,可以直接运行,方便部署

4.Linux调试器-gdb

4.1 背景

  • 程序的发布方式有两种,debug模式和release模式
  • Linux gcc/g++出来的二进制程序,默认是release模式
  • 要使用gdb调试,必须在源代码生成二进制程序的时候, 加上 -g 选项

4.2 开始使用

gdb binFile

退出: 

ctrl + d 或 quit

调试命令:

  • list/l 行号:显示binFile源代码,接着上次的位置往下列,每次列10行。
  • list/l 函数名:列出某个函数的源代码。
  • r或run:运行程序。
  • n 或 next:单条执行。
  • s或step:进入函数调用
  • break(b) 行号:在某一行设置断点
  • break 函数名:在某个函数开头设置断点
  • info break :查看断点信息。
  • finish:执行到当前函数返回,然后挺下来等待命令
  • print(p):打印表达式的值,通过表达式可以修改变量的值或者调用函数
  • p 变量:打印变量值。
  • set var:修改变量的值
  • continue(或c):从当前位置开始连续而非单步执行程序
  • run(或r):从开始连续而非单步执行程序
  • delete breakpoints:删除所有断点
  • delete breakpoints n:删除序号为n的断点
  • disable breakpoints:禁用断点
  • enable breakpoints:启用断点
  • info(或i) breakpoints:参看当前设置了哪些断点
  • display 变量名:跟踪查看一个变量,每次停下来都显示它的值
  • undisplay:取消对先前设置的那些变量的跟踪
  • until X行号:跳至X行
  • breaktrace(或bt):查看各级函数调用及参数
  • info(i) locals:查看当前栈帧局部变量的值
  • quit:退出gdb

1. list

2. run(运行)

3. break(断点)

4. info break(断点信息)

5. delete breakpoints(n)(删除断点)

6. disable breakpoints(禁用断点)

run的时候会在断点处停下来,如果禁用了断点,则该断点无作用

7. enable breakpoints(启用断点)

8. n 或 next:单条执行(逐过程)

在14行打上断点

逐过程不会进入到函数,会将函数当成一句代码执行

9. s或step:进入函数调用(逐语句)

s进入函数内部,逐语句执行

10. p 变量:打印变量值

11. display 变量名:跟踪查看一个变量

每次停下来都显示它的值

12. undisplay:取消对先前设置的变量的跟踪

13. until X行号:跳至X行

4.3 理解

  • quit:退出gdb
  • list/l:l 文件名:行号/函数名,l 行号/函数名
  • b:b 文件名:行号/函数名,b 行号/函数名
  • info/i:info b
  • d:d 断点编号
  • disable/enable 断点编号:使能(关闭/打开)断点
  • next/n:逐过程 F10
  • step/s:逐语句 F11
  • print/p:查看变量内容&&地址 a && &a
  • display:a &a
  • undisplay:number
  • continue/c:运行至下一个断点处
  • finish:运行结束所在函数,就停下来
  • until:跳转至指定行,中间的代码都运行

5.git操作 - gitee

5.1 使用 git 命令行

安装 git

yum install git

5.2 使用gitee

5.2.1 注册账户

工作台 - Gitee.com

进入gitee,根据提示注册并登录

5.2.2 新建仓库

  • 仓库名称
  • 仓库简介
  • 初始换仓库

5.3 Linux-git操作

进入仓库,选择“克隆/下载”

复制下面的两行命令进行git配置

然后将仓库clone到用户目录下

这时候用户目录下就多了这个仓库

5.3.1 git三板斧

想要将本地的代码上传到git,需要掌握三板斧的用法:add - commit - push

我们在这个目录下新建一个文件夹存放将要上传的文件,以test1为例

git add

将目录下的所有文件都git add

git commit

git commit -m指令,引号内是对文件的描述,不能省略

git push

最后直接git push

这时候我们就会看到今天的小绿点就出来了

同时文件也上传到了gitee仓库

5.3.2 git删除操作

  • git rm
  • git 三板斧

git删除很简单,用git rm删除,接着三板斧即可

比如我们要删除仓库里的test

千万要记住自己的用户名和密码(username password)

这样我们的删除操作就完成了

5.3.3 git日志

我们可以查看git的操作日志:git log

该时刻的操作和所有的信息都能显示出来

5.3.4 图示git

6.Linux项目自动化构建工具-make/Makefile

6.1 背景

会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力

一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作

makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率

make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法

make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建

6.2 实例代码

我们先创建一个test.c文件,并在里面编写一些代码

然后我们再创建一个makefile/Makfile,大小写都是可以的,然后可以编写这样的指令

随后我们保存退出,在命令行中输入make指令

他直接执行了这段指令,再输入这段指令

同样也能执行这段指令    

6.3 理解

makefile文件写好之后, 当我们在命令行中输入make指令的时候,对应的make程序就会在当前目录下找makefile这个文件,并读取makefile中的内容,根据依赖关系可以知道我们要通过依赖方法形成目标文件

6.4 原理

make是如何工作的,在默认的方式下,也就是我们只输入make命令。那么,

  1. make会在当前目录下找名字叫“Makefile”或“makefile”的文件
  2. 如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“hello”这个文件,并把这个文件作为最终的目标文件
  3. 如果hello文件不存在,或是hello所依赖的后面的hello.o文件的文件修改时间要比hello这个文件新(可以用 touch 测试),那么,他就会执行后面所定义的命令来生成hello这个文件
  4. 如果hello所依赖的hello.o文件不存在,那么make会在当前文件中找目标为hello.o文件的依赖性,如果找到则再根据那一个规则生成hello.o文件(这有点像一个堆栈的过程)
  5. 当然,你的C文件和H文件是存在的啦,于是make会生成 hello.o 文件,然后再用 hello.o 文件声明make的终极任务,也就是执行文件hello了
  6. 这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件
  7. 在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make根本不理
  8. make只管文件的依赖性,即如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起,我就不工作啦
#include <stdio.h>
int main()
{
 printf("hello Makefile!\n");
 return 0;
}
Makefile文件 
hello:hello.o
    gcc hello.o -o hello
hello.o:hello.s
    gcc -c hello.s -o hello.o 
hello.s:hello.i 
    gcc -S hello.i -o hello.s 
hello.i:hello.c 
    gcc -E hello.c -o hello.i
.PHONY:clean
clean:
    rm -f hello.i hello.s hello.o hello

6.4.1 依赖关系

  • 上面的文件 hello ,它依赖 hello.o
  • hello.o , 它依赖 hello.s
  • hello.s , 它依赖 hello.i
  • hello.i , 它依赖 hello.c

6.4.2 依赖方法

  • gcc hello.* -option hello.* ,就是与之对应的依赖关系

6.4.3 项目清理

工程是需要被清理的

  • 像clean这种,没有被第一个目标文件直接或间接关联,那么它后面所定义的命令将不会被自动执行,不过,我们可以显示要make执行。即命令——“make clean”,以此来清除所有的目标文件,以便重编译
  • 但是一般我们这种clean的目标文件,我们将它设置为伪目标,用 .PHONY 修饰,伪目标的特性是,总是被执行的
  • 可以将我们的 hello 目标文件声明成伪目标,测试一下

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1530036.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

windows下的IDEA运用Scala 编写的 Apache Spark 应用程序

目录 一.环境要求 虚拟机环境 1.linux操作系统 2.jdk 3.Hadoop环境 4.spark 5.scala Windows环境 1.jdk 2.Hadoop&#xff08;同上&#xff09; 3.Scala 4. 安装winutils 二.IDEA的安装 idea下载 1、网站 2、下载 3、 安装 idea的配置 1.汉化 2.下载scala…

Windows电脑上如何进行硬盘分区操作!

在Windows操作系统环境下,对电脑硬盘进行分区是一种常见的硬盘管理手段,它可以帮助用户更好地组织和管理存储空间,确保操作系统、应用程序和用户数据各有所属。本文将详细介绍在Windows PC上进行硬盘分区的步骤,适用于Windows 7到Windows 11等不同版本的操作系统。 步骤一:…

C# visual studio 2022 学习2

类成员&#xff1a; 1.字段成员 字段只是类中声明的一个变量&#xff0c;用来在对象中存储信息。 &#xff08;1&#xff09;.静态字段 使用static关键字修饰的就是静态字段&#xff0c;静态字段属于类而不属于某个类实例&#xff0c;对它的访问使用“类名.静态字段名” &…

el-tree 设置默认展开指定层级

el-tree默认关闭所有选项&#xff0c;但是有添加或者编辑删除的情况下&#xff0c;需要刷新接口&#xff0c;此时会又要关闭所有选项&#xff1b; 需求&#xff1a;在编辑时、添加、删除 需要将该内容默认展开 <el-tree :default-expanded-keys"expandedkeys":da…

JS+CSS3点击粒子烟花动画js特效

JSCSS3点击粒子烟花动画js特效 JSCSS3点击粒子烟花动画js特效

大数据技术学习笔记(十三)—— HBase

目录 1 Hbase 概述1.1 Hbase 定义1.2 HBase 数据模型1.2.1 HBase 逻辑结构1.2.2 HBase 物理存储结构1.2.3 数据模型 1.3 HBase 基本架构 2 HBase Shell 操作2.1 基本操作2.2 namespace 操作2.3 表操作 3 HBase 原理深入3.1 RegionServer 架构3.2 HBase 写流程3.3 MemStore Flus…

【技术栈】Redis 企业级解决方案

​ SueWakeup 个人主页&#xff1a;SueWakeup ​​​​​​​ 系列专栏&#xff1a;学习技术栈 ​​​​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​ 个性签名&…

C# 使用OpenCvSharp4将Bitmap合成为MP4视频的环境

环境安装步骤&#xff1a; 在VS中选中项目或者解决方案&#xff0c;鼠标右键&#xff0c;选择“管理Nuget包”&#xff0c;在浏览窗口中搜索OpenCVSharp4 1.搜索OpenCvSharp4,选择4.8.0版本&#xff0c;点击安装 2.搜索OpenCvSharp4.runtime.win,选择4.8.0版本&#xff0c;点…

vue3 + vite 实现一个动态路由加载功能

假设后端返回的格式是这样子 {"menu": [{"path": "/admin","name": "adminLayout","redirect": "/admin/index","componentPath": "/layout/admin/index.vue","children&quo…

Could not locate zlibwapi.dll. Please make sure it is in your library path!

背景 运行PaddleOCR时&#xff0c;用的CUDA11.6配的是cuDNN8.4。但是运行后却报错如下。 解决手段 去网上找到这两个文件&#xff0c;现在英伟达好像不能下载了&#xff0c;但是可以去网盘下载。然后把dll文件放入CUDA11.6文件下的bin目录&#xff0c;而lib文件放入CUDA11.6文…

基于YOLOv8的航空遥感飞机小目标检测

&#x1f4a1;&#x1f4a1;&#x1f4a1;本文摘要&#xff1a;基于YOLOv8的航空遥感飞机小目标检测&#xff0c;阐述了整个数据制作和训练可视化过程 1.YOLOv8介绍 Ultralytics YOLOv8是Ultralytics公司开发的YOLO目标检测和图像分割模型的最新版本。YOLOv8是一种尖端的、最先…

js检测数据类型方式(typeof instanceof Object.prototype.toString.call())

typeof 使用 typeof 检测数据类型&#xff0c;首先返回的都是一个字符串&#xff0c;其次字符串中包含了对应的数据类型&#xff1b; 缺点&#xff1a; typeof null "object"不能具体细分是数组、正则还是对象中其他值&#xff0c;使用 typeof 检测数据类型对于对…

微服务day03 -- Docker

1.初识Docker 1.1.什么是Docker 微服务虽然具备各种各样的优势&#xff0c;但服务的拆分通用给部署带来了很大的麻烦。 分布式系统中&#xff0c;依赖的组件非常多&#xff0c;不同组件之间部署时往往会产生一些冲突。 在数百上千台服务中重复部署&#xff0c;环境不一定一致…

59、服务攻防——中间件安全CVE复现IISApacheTomcatNginx

文章目录 中间件——IIS漏洞中间件——Nginx漏洞中间件——Apache中间件——Tomcat 中间件&#xff1a;IIS、Apache、Nginx、Tomcat、Docker、Weblogic、JBoss、WebSphere、Jenkinsphp框架&#xff1a;Laravel、Thinkphppythonl框架&#xff1a;Flaskjs框架&#xff1a;jQueryj…

vue+elementui中table实现单选行功能

el-table插件可以选择行&#xff0c;但是只能多选&#xff0c;而项目中有单选的需求。 效果如下图所示&#xff0c;点击行或者点击复选框都可以选中行&#xff08;高亮&#xff0c;复选框选中&#xff09;&#xff0c;并且每次只选中当前行&#xff0c;之前选中的行清空。点击标…

Panasonic松下PLC如何数据采集?如何实现快速接入IIOT云平台?

在工业自动化领域&#xff0c;数据采集与远程控制是提升生产效率、优化资源配置的关键环节。对于使用Panasonic松下PLC的用户来说&#xff0c;如何实现高效、稳定的数据采集&#xff0c;并快速接入IIOT云平台&#xff0c;是摆在他们面前的重要课题。HiWoo Box工业物联网关以其强…

TikTok云手机是什么原理?

随着社交媒体的快速发展和普及&#xff0c;TikTok已成为全球最受欢迎的短视频平台之一&#xff0c;吸引了数以亿计的用户。在TikTok上&#xff0c;许多用户和内容创作者都希望能够更灵活地管理和运营多个账号&#xff0c;这就需要借助云手机技术。那么&#xff0c;TikTok云手机…

通过el-table实现表格穿梭框

element-ui自带的el-transfer界面比较简单&#xff0c;通过el-table实现表格形式的穿梭框功能 首先是效果图 示例图样式比较简单&#xff0c;但是el-table是完全通过div包裹的&#xff0c;所以里面可以自己添加更多的其他组件实现想要的功能 <div style"display: flex…

微信小程序 ---- 慕尚花坊 结算支付

结算支付 01. 配置分包并跳转到结算页面 思路分析&#xff1a; 随着项目功能的增加&#xff0c;项目体积也随着增大&#xff0c;从而影响小程序的加载速度&#xff0c;影响用户的体验。 因此我们需要将 结算支付 功能配置成一个分包&#xff0c; 当用户在访问设置页面时&a…

鸿蒙Harmony应用开发—ArkTS声明式开发(画布组件:Path2D)

路径对象&#xff0c;支持通过对象的接口进行路径的描述&#xff0c;并通过Canvas的stroke接口或者fill接口进行绘制。 说明&#xff1a; 从 API Version 8 开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 addPath addPath(path: path2D,…