当前位置:   article > 正文

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

linux 编译器

主页:醋溜马桶圈-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只管文件的依赖性,即如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起,我就不工作啦
  1. #include <stdio.h>
  2. int main()
  3. {
  4. printf("hello Makefile!\n");
  5. return 0;
  6. }
  1. Makefile文件
  2. hello:hello.o
  3. gcc hello.o -o hello
  4. hello.o:hello.s
  5. gcc -c hello.s -o hello.o
  6. hello.s:hello.i
  7. gcc -S hello.i -o hello.s
  8. hello.i:hello.c
  9. gcc -E hello.c -o hello.i
  10. .PHONY:clean
  11. clean:
  12. 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 目标文件声明成伪目标,测试一下
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/代码探险家/article/detail/927509
推荐阅读
相关标签
  

闽ICP备14008679号