【Linux】gcc与make、makefile

news2024/11/6 3:08:10

文章目录

  • 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.coloradmin.cn/o/1505681.html

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

相关文章

Delphi 的Read 与Readln 的区别

结合运行窗口&#xff0c;你输入1 2 3 4 这是一行ReadLn在读入时把这四个数当成一行&#xff0c;read(a,b)只读入了前两个数&#xff1a;1 2&#xff0c;就准备读下一行了&#xff0c;下一行输入3&#xff0c;再下一行输入2&#xff0c;所以输出1232&#xff1b; Read是逐个读…

【MySQL 系列】MySQL 语句篇_DQL 语句

DQL&#xff08;Data Query Language&#xff09;&#xff0c;即数据查询语言&#xff0c;用来查询数据记录。DQL 基本结构由 SELECT FROM、WHERE、JOIN 等子句构成。 DQL 语句并不会改变数据库&#xff0c;而是让数据库将查询结果发送结果集给客户端&#xff0c;返回的结果是一…

IDEA打开项目文件目录不见了

偶尔发生新拉下来的代码&#xff0c;或者旧代码修改了包名&#xff0c;项目名称等&#xff0c;idea左侧project一栏不显示代码的文件目录。例如下面此时不要慌张&#xff0c;不用删除项目重新拉取&#xff0c;通过以下方式解决&#xff1a; 本人尝试能够解决&#xff0c;如果无…

Learn OpenGL 05 变换

万向节死锁 万向节死锁&#xff08;Gimbal Lock&#xff09;是用欧拉角定义旋转时&#xff0c;产生的在某一情况下旋转轴重合导致的系统丢失自由度的情况&#xff0c;一种最简单的解决方式是调整三维软件中的旋转轴顺序来避免该情况发生。 也就是说当中间轴旋转至90的时候就会…

Vue+ElementUI启动vue卡死的问题

0 引言 今天&#xff0c;博主在学习vueelementui的时候遇到一个问题&#xff0c;卡了博主很久。 1 问题复现 在vue页面的<template>标签中写入两个<div>标签&#xff0c; <template><div><h1>第一个div标签</h1><el-table></…

vue学习笔记21-组件传递数据_Props

组件与组件之间不是完全独立的&#xff0c;而是有交集的&#xff0c;那就是组件与组件之间是可以传递数据的 传递数据的解决方案就是props 父级&#xff1a; 在父级中引入子集 <template><h3>Parent</h3><Child/> </template><script> i…

适配器模式已经在SpringMVC中的源码实现

介绍&#xff1a; 1、适配器模式将某个类的接口转换成客户端期望的另一种接口表示 2、目的&#xff1a;兼容性&#xff0c;让原本因接口不匹配不能一起工作的两个类可以协同工作。其别名为&#xff1a;包装器。 3、属于&#xff1a;结构型模式 4、分3类&#xff1a;1&#xff0…

方程式工具包远程溢出漏洞图形界面版V0.3(内置永恒之蓝、永恒冠军、永恒浪漫等)

Part1 前言 大家好&#xff0c;我是ABC_123。我从年前到现在&#xff0c;一直在整理曾经写过的红队工具&#xff0c;逐步把自己认为比较好用的原创工具发出来给大家用一用&#xff0c;方便大家在日常的攻防比赛、红队评估项目中解放双手&#xff0c;节省时间精力和体力。本期给…

MySQL中常用的操作语句已汇总

目录 一、库语句 1.查询现有数据库 2.创建数据库 3.选中数据库 ​编辑 4.删除数据库 二、初阶表操作 1.查看数据库现有表 2.查看表结构 3.创建表 4.删除表 5.全列查询 6.删除表2 7.修改操作 三、插入操作 1.全列插入 2.指定列插入 3.一次插入多组数据 4.插入…

SpringBoot集成netty实现websocket通信

实现推送消息给指定的用户 一、依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://m…

redis-集群 原生部署和工具自动部署

什么redis集群&#xff1f; redis集群是一个提供在多个redis节点之间共享数据的程序集。它并不像redis主从复制模式那样仅提供一个master节点来提供写服务&#xff0c;而是会提供多个master节点来提供写服务&#xff0c;每个master节点中存储的数据都不一样&#xff0c;这些数据…

HarmonyOS系统开发基础环境搭建

目录 一 鸿蒙介绍&#xff1a; 1.1 HarmonyOS系统 1.2 HarmonyOS软件编程语言 二 HarmonyOS编程环境搭建 1.1 官网下载地址 1.2搭建开发流程 1.3 创建安装目录 1.4 下载DevEco Studio​编辑 1.5 下载后点击安装 1.6 自动添加桌面快捷和bin路径 ​编辑1.7 安装好运行 …

[Angular 基础] - 表单:模板驱动表单

[Angular 基础] - 表单&#xff1a;模板驱动表单 之前的笔记&#xff1a; [Angular 基础] - routing 路由(上) [Angular 基础] - routing 路由(下) [Angular 基础] - Observable Angular 内置两种表单的支持&#xff0c;这篇写的就是第一种&#xff0c;即模板驱动表单 (Tem…

wps由于找不到krpt.dll,无法继续执行代码的解决方法

遇到由于找不到krpt.dll,无法继续执行代码的问题时&#xff0c;理解如何修复这个问题变得至关重要。本文会教大家krpt.dll的恢复流程&#xff0c;并介绍该DLL文件的相关属性。我们将一步步指导你如何处理缺失文件的情况&#xff0c;让你能够解决阻碍代码正常运行的障碍&#xf…

C语言初学10:typedef

一、作用 为用户定义的数据类型取一个新名字 二、对结构体使用typedef定义新的数据类型名字 #include <stdio.h> #include <string.h>typedef struct Books //使用 typedef 来定义一个新的数据类型名字 {char title[50];} book;int main( ) {//book是typedef定…

背包问题算法

背包问题算法 0-1背包问题二维数组一维数组 完全背包问题二维数组一维数组 多重背包问题一维数组 0-1背包问题 问题&#xff1a;背包的容量为9&#xff0c;有重量分别为[2, 4, 6, 9]的四个物品&#xff0c;价值分别为[3, 4, 5, 6]&#xff0c;求背包能装的物品的最大价值是多少…

LiveNVR监控流媒体Onvif/RTSP功能-支持云端录像监控视频集中存储录像回看录像计划配置NVR硬件设备录像回看

LiveNVR支持云端录像监控视频集中存储录像回看录像计划配置NVR硬件设备录像回看 1、流媒体服务软件2、录像回看3、查看录像3.1、时间轴视图3.2、列表视图 4、如何分享时间轴录像回看&#xff1f;5、iframe集成示例7、录像计划7、相关问题7.1、录像存储位置如何配置&#xff1f;…

【电路】工作于直流4.5V电压的声控小灯

这个声控小灯用于控制4.5V直流供电的小灯泡&#xff0c;可用作学生实验也可用作声控夜光小灯。电路主要由5G555时基集成电路和一些分立元件组成&#xff0c;如下图所示&#xff1a; 工作原理 压电陶瓷片B与晶体三极管VT1&#xff0c;电阻R1&#xff0c;和电阻R2等组成了声控脉…

数据结构之单链表及其实现!

目录 ​编辑 1. 顺序表的问题及思考 2.链表的概念结构和分类 2.1 概念及结构 2.2 分类 3. 单链表的实现 3.1 新节点的创建 3.2 打印单链表 3.3 头插 3.4 头删 3.5 尾插 3.6 尾删 3.7 查找元素X 3.8 在pos位置修改 3.9 在任意位置之前插入 3.10 在任意位置删除…

【Primsjs】vue+代码高亮

效果 括号变色括号鼠标移入高亮效果 代码效果 目录树 在这里插入图片描述 安装 cnpm i primsjs简介 文档&#xff08;点我进去&#xff09; 备用地址-https://prismjs.com/docs/index.html Primsjs使用 导入配置插件 注意&#xff1a;需要什么插件就导入什么插件 码 &l…