【Linux】gcc与make、makefile

文章目录

  • 1 gcc/g++
    • 1.1 预处理
    • 1.2 编译
    • 1.3 汇编
    • 1.4 链接
      • 1.4.1 静态链接
      • 1.4.2 动态链接
  • 2 make和makefile
    • 2.1 依赖关系
    • 2.2 依赖方法
    • 2.3 伪目标
  • 3 总结

1 gcc/g++

在这里插入图片描述
当我们创建一个文件,并向里面写入代码,此时,我们该如何使我们的代码能够运行起来呢?

如果是在windows的vs下,只需要点击运行就行了,现在在Linux下,该如何运行?

我们需要使用gcc编译器来编译已经写好的test.c源文件

编译之后,会在当前目录之下生成可执行程序,运行可执行程序即可

在这里插入图片描述
使用红框中的命令gcc test.c -o test 就完成了对源文件的编译。

之后,生成了可执行程序test.

运行test即可执行我们的可执行程序。

补充:c语言的程序用gcc编译,c++的程序用g++编译

  • 格式:
    gcc - 选项 源文件名 -o 目标文件名
  • 选项:
    -E 从当前文件开始,在预处理完成之后停止, 生成的文件后缀一般加i
    -S 从当前文件开始,在编译完成之后停止, 生成的文件后缀一般加s
    -c 从当前文件开始,在汇编完成之后停止, 生成的文件后缀一般加o

1.1 预处理

预处理的作用:

  1. 去除注释
  2. 展开头文件
  3. 处理条件编译
  4. 进行宏替换

命令: gcc -E 文件名.c -o 文件名.i

在这里插入图片描述
左边是test.c文件,右边是test.i文件(预处理文件)
在这里插入图片描述

1.2 编译

命令: gcc -S 文件名.i -o 文件名.s
功能:将预处理文件编译成汇编语言
在这里插入图片描述

在这里插入图片描述

1.3 汇编

命令: gcc -c 文件名.s -o 文件名.o
功能:将编译生成的.s文件中的内容转变成机器能识别的二进制机器码。
在这里插入图片描述
可以通过od命令查看.o文件
将二进制机器码以十六进制的形式显示出来。
在这里插入图片描述

1.4 链接

到这一步时候,我们的文件是,o的汇编文件。

这里有一个问题:我们写的程序中,使用到了printf()函数,但是我们并没有写printf()函数的实现方法和定义等,为什么执行程序的时候不会报错?

因为我们使用了库函数

printf()函数很明显是库函数。假设我们不包含<stdio.h>头文件,我们的程序必然会报错。

我们包了<stdio.h>文件之后就能使用了吗?

也不是,因为我们知道.h只是一个头文件,相当于有一个函数的声明,但是没有函数的具体定义,函数的具体定义肯定是一个文件。

假设库的创建者写了1000个函数,分为两个文件。其中,函数的实现叫做c和定义叫做c.h。

库的创建者不想给我们看函数的具体实现。所以对这个库进行的封装。但是他必须提供库的使用方法,所以又把头文件给了我们,提供给我们具体的使用方法。

我们通过头文件得知使用方法之后,在我们的c程序执行到库函数时候,就会链接到库中的库函数。库函数也是.o目标文件,将我们自己的程序和库函数链接到一起,就会生成可执行程序.exe。

那么,该如何找到库呢?

在没有特别指定时,gcc 会到系统默认的搜索路径“/usr/lib”下进行查找。

链接的库分为静态库和动态库。

1.4.1 静态链接

在这里插入图片描述

  1. 当我们的函数执行到库函数的时候,跳转到链接的库函数,将库函数中该函数的实现拷贝到当前程序文件中。
  2. 再此之后再生成可执行文件。

静态链接的指令gcc 文件名.o -o 文件名 -static

在这里插入图片描述

1.4.2 动态链接

在这里插入图片描述

  1. 当执行到库函数时,跳转到动态库中,找到该函数的.o文件,去链接标准库中库函数的.o文件。
  2. 链接完之后再跳转回来。

在这里插入图片描述
在这里插入图片描述
通过ldd命令可以查看a.out链接的动态库。
图中的红框就是我们链接的动态库c

库的名称为去掉前缀去掉后缀,图中就是去掉前缀lib,去掉后缀.so,最后得到c

通过file指令查看文件的属性
在这里插入图片描述
黄色框中说明这是一个动态链接,链接的是动态库。

动态链接和静态链接的区别是什么?
在这里插入图片描述
通过上图可以看出静态链接比动态链接之后的文件大很多。

这是因为动态链接是直接跳转,而静态链接是将静态库中的内容拷贝到文件中

总结

  • 静态库或者动态库一个系统只有一个,所有使用系统的用户都在使用同一个库。
  • 静态链接后的可执行程序不会受到静态库升级或者被删除的影响,而动态库会受到影响。
  • 系统为了我们编程,提供了标准库的头文件.h,和动静态库.so/.a,头文件是为了告诉我们怎么使用库函数,动静态库中提供了库函数的具体实现方法。

2 make和makefile

make 是方法,makefile是文件

创建makefile文件
在这里插入图片描述
写入makefile文件
在这里插入图片描述

效果
在这里插入图片描述
从上面的操作中,我们可以看到,以前我们每次编译文件,都需要输入gcc等一系列命令。现在只需要使用make,就自动编译成功了。

  • makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
  • 一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作。

接下来分步解析。

2.1 依赖关系

什么是依赖关系?
a:b -----> 叫做a依赖b,有了b的存在才会有a的存在。

在makefile中,gcc编译的时候有哪些依赖关系呢?

在这里插入图片描述

2.2 依赖方法

依赖关系解决的谁以来谁的问题

依赖方法解决的是怎样依赖的问题

在这里插入图片描述
红框的内容就是依赖方法

在makefile中依赖关系和依赖方法是必须写的,并且必须是一一对应的

2.3 伪目标

在makefile中同样是可以删除文件的。

在这里插入图片描述
执行情况
在这里插入图片描述
其中,.PHONY:clean 这句话中.PHONY就是伪目标,clean被.PHONY修饰的

  • 被.PHONY修饰的对象就是一个伪目标。
  • 伪目标总是被执行。

如何理解伪目标总是被执行这句话?

首先理解什么文件不是总被执行。

在这里插入图片描述
可以看到,在执行第一次make的时候,可以正常执行;执行第二次make的时候就不能了。

为什么呢?

在这里插入图片描述

在使用stat命令之后,可以看到一个文件的ACM时间,分别是图上所示。

我们使用ll命令显示的就是文件的内容修改时间

在这里插入图片描述

可以看到test.c文件的最后一次被修改时间比test的最后一次被修改时间早。

这就意味着:可执行文件如果再次执行,其实内容是没有改变的。

如果test.c文件在test文件之后又被修改过,那么Modify时间应该比test文件的时间晚,这样再次编译的时候才会有效果。而如果test.c的时间比test时间早,说明test.c文件没有被修改过。因此也就没有再次编译的必要。

这是编译器为了更高效的举动。

验证
在这里插入图片描述
从上面可以知道,make不是总被执行,那么。伪目标是总被执行的,怎么验证?

在这里插入图片描述
只要执行make clean 就一直会执行,不会出现阻碍。

而clean正是被.PHONY修饰的伪目标

在这里插入图片描述

执行:
在这里插入图片描述
发现给make加上伪目标之后,make也总是被执行。

**clean:**之后没有东西,说明依赖关系也可以为空

3 总结

  1. 编译链接分为:预处理、编译、汇编、链接四个部分。使用到的命令如下:
    在这里插入图片描述
  • .c文件预处理变成.i文件
  • .i文件编译变成.s文件
  • .s文件汇编变成.o文件
  • .o文件链接变成可执行程序

其中,链接分为动态链接和静态链接。
静态链接将静态库中的.o程序拷贝到我们的程序,执行静态链接需要到系统默认的路径usr/lib中去找静态库,如果找不到就会报链接错误。

如果使用的是第三方库,需要用特定的方法链接到库。

  1. makefile中有:依赖关系,依赖方法和伪目标。
    其中,依赖关系和依赖方法是一一对应的。
    依赖关系也可以为空。

伪目标.PHONY表示总是执行

没有伪目标的文件通过判断文件的Modify时间来决定是否编译:

  1. 如果.c文件的Modify时间于可执行文件 ---- 不执行
  2. 如果.c文件的Modify时间于可执行文件 ---- 执行

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java中使用rabbitmq

文章目录 前言一、引入和配置1.引入2.配置 二、使用1.队列2.发布/订阅2.1 fanout(广播)2.2 direct(Routing/路由)2.3 Topics(主题)2.4 Headers 总结 前言 mq常用于业务解耦、流量削峰和异步通信,rabbitmq是使用范围较广,比较稳定的一款开源产品,接下来我们使用springboot的sta…

保姆级认识AVL树【C++】(三种insert情况 || 四种旋转方法)

目录 前言 一&#xff0c;AVL概念 二&#xff0c;基础框架 三&#xff0c;insert 1. 插入三种情况 2. 四种旋转方法 法一&#xff1a;左单旋法 法二&#xff1a;右单旋法 法三&#xff1a;先左后右双旋法 法四&#xff1a;先右后左双旋法 测试&#xff08;判断一棵树…

修改简化docker命令

修改|简化docker命令 使用命令打开 .bashrc 文件&#xff1a; vim ~/.bashrc在文件中添加类似以下行来创建别名&#xff1a; # 查看所有容器 alias disdocker images # 查看运行容器 alias dpsdocker ps # 查看所有容器 alias dpsadocker ps -a # 停止容器 alias dsdocker s…

基于智慧灯杆的智慧城市解决方案(2)

功能规划 智慧照明功能 智慧路灯的基本功能仍然是道路照明, 因此对照明功能的智慧化提升是最基本的一项要求。 对道路照明管理进行智慧化提升, 实施智慧照明, 必然将成为智慧城市中道路照明发展的主要方向之一。 智慧照明是集计算机网络技术、 通信技术、 控制技术、 数据…

Data Concerns Modeling Concerns

How was the data you are using collected? What assumptions is your model making by learning from this dataset? Is this dataset representative enough to produce a useful model? How could the results of your work be misused? What is the intended use and …

第15章——西瓜书规则学习

1.序贯覆盖 序贯覆盖是一种在规则学习中常用的策略&#xff0c;它通过逐步构建规则集来覆盖训练数据中的样本。该策略采用迭代的方式&#xff0c;每次从训练数据中选择一部分未被覆盖的样本&#xff0c;学习一条能够覆盖这些样本的规则&#xff0c;然后将这条规则加入到规则集中…

【Python】成功解决ModuleNotFoundError: No module named ‘matplotlib‘

【Python】成功解决ModuleNotFoundError: No module named ‘matplotlib’ &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程&#x1f448…

Linux系统安装及简单操作

目录 一、Linux系统安装 二、Linux系统启动 三、Linux系统本地登录 四、Linux系统操作方式 五、Linux的七种运行级别&#xff08;runlevel&#xff09; 六、shell 七、命令 一、Linux系统安装 场景1&#xff1a;直接通过光盘安装到硬件上&#xff08;方法和Windows安装…

基于springboot实现摄影网站系统项目【项目源码】

基于springboot实现摄影网站系统演示 摘要 随着时代的进步&#xff0c;社会生产力高速发展&#xff0c;新技术层出不穷信息量急剧膨胀&#xff0c;整个社会已成为信息化的社会人们对信息和数据的利用和处理已经进入自动化、网络化和社会化的阶段。如在查找情报资料、处理银行账…

虚拟化

什么是虚拟化 虚拟化&#xff08;Virtualization&#xff09;是一种资源分配和管理技术&#xff0c;是将计算机的各种实体资源,比如CPU、内存、磁盘空间、网络适配器等&#xff0c;进行抽象转换后虚拟的设备,可以实现灵活地分割、组合为一个或多个计算机配置环境&#xff0c;并…

el-form-item内的el-select如何自适应宽度

最近在使用element-ui做后台管理的时候&#xff0c;有个需求是在弹窗组件里面&#xff0c;添加一个el-select下拉框选项&#xff0c;但是给el-select设置的宽度无法自适应&#xff0c;原因很简单&#xff0c;我们不需要设置固定宽度&#xff0c;设置百分比就行了&#xff0c;让…

CURE-Net: A Cascaded Deep Network for Underwater Image Enhancement

文章目录 论文结构 及 读论文的方法总结论文理解看图AbstractIntroductionRELATED WORKPROPOSED METHODA Philosophy of Model DesignB Framework of CURE-NetC Proposed GESNet and ORSNetD Proposed DEB and SRBE Loss Function Experiment And ResultA Implementation Detai…