Linux之手把手教你捋清楚make和makefile

news2025/7/6 17:32:13

文章目录

  • 背景
  • 简单介绍make和makefile
  • 依赖关系和依赖方法
  • 项目清理以及伪目标

背景

以往的C语言编程,我们一般都在一些像VS2019这样的集成开发环境(IDE)下编写,一个工程中的源文件不计其数,其按类型、功能、模块分别放在若干个目录中,但是在Linux下怎么做类似VS下的工作呢?这就要用到make和makefile了。

简单介绍make和makefile

  • 使用makefile你可以自己定义一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,甚至于进行更复杂的功能操作。
  • makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完成自动编译,极大的提高了软件开发的效率。
  • make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。
  • make是一条命令,默认的情况下,make命令会在当前目录下按顺序找寻文件名为“GNUmakefile”、“makefile”、“Makefile”的文件 (后面说的makefile默认指的就是这三个文件) 找到了就解释这个文件。
  • makefile里其实写的就是依赖关系和依赖方法

依赖关系和依赖方法

例子一:拿一个最简单的程序输出hello world为例。先创建一个test.c,使用vim工具来写我们的hello word代码。

$ touch test.c
$ vim test.c
#include<stdio.h>                            
  int main()
  {
     printf("hello world\n");
     return 0;
  }

然后再创建一个makefile文件,使用vim工具

$ touch makefile
$ vim makefile

来编写makefile里的依赖关系和依赖方法。

hello:test.c  #依赖关系
	gcc test.c -o hello  #依赖方法 

拿很简单的一个生活例子来解释依赖关系和依赖方法,每月的月底上学的孩子就会跟父母要这个月的生活费,那么依赖关系就是 孩子:父母,也就是前者依赖后者;依赖方法就是 要生活费,二者缺一不可。

这里也一样hello是我们通过gcc命令编译test.c这个源文件最后生成的可执行文件。所以依赖关系hello:test.c,(hello依赖test.c)依赖方法就是编译test.c这个源文件然后把形成的可执行程序放在hello中这个过程。而且千万要注意写完依赖关系,依赖方法必须是以Tab键开头的

当然像上面的gcc一步到位很爽,但是其实也可以把预处理、编译、汇编、链接这四个过程再makefile中分开来写。对于gcc预处理、编译、汇编、链接各个过程生成的i、s、o文件有不了解的老铁可以看这篇文章Linux编译器-gcc/g++的使用

mycode:mycode.o
	gcc mycode.o -o mycode
mycode.o:mycode.s
	gcc-c mycode.s -o mycode.o
mycode.s:mycode.i
    gcc-S mycode.i -o mycode.s
mycode.i :mycode.c
   	gcc -E mycode.c -o mycode.i

分析:像上面这样写我们在外面输入make之后从上到下执行,我想要得到mycode文件需要mycode.o文件,但是mycode.o还需要mycode.s,想要得到mycode.s就需要mycode.i文件,就这样顺着这个关系一直向下执行,直到最后 gcc -E mycode.c -o mycode.i执行完之后才能得到mycode,类似于栈结构。总结来说使用makefile你可以自己给他定义推导结构。

项目清理以及伪目标

工程是需要被清理的。
如下所示我们可以在makefile文件中添加一些清理的代码

hello:test.c  #依赖关系
	gcc test.c -o hello  #依赖方法

.PHONY:clean  #伪目标
clean:
	rm -f hello

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

对于“总是可以被执行的”的解释:
就像上面的hello目标文件生成完一次之后,如果你没有改变test.c的内容,那么hello目标文件是不能再次被生成的。
原因:我们随便创建一个文件使用stat指令来显示文件/文件系统的详细信息就可以看到这里有三个时间。从上往下分别是访问时间、内容修改时间、属性修改时间。
在这里插入图片描述
返回我们刚才的hello world程序,make之后会产生一个hello可执行文件,那么这个内容修改时间就必定比test.cC语言源文件的内容修改时间新,它内部根据这个时间的新旧就可以判断本次程序该不该再次编译。
而我们给它在前面加上.PHONY变成了伪目标就可以重复的执行而不受上面这个规则的限制。当然可以将我们的 hello 目标文件声明成伪目标。


好了今天的分享就到此为止了
最后:如果你觉得对你有用就一键三连吧,哪里有没看懂的地方或者哪里有错误可以在评论区留言欢迎批评指正,作者看到的话会第一时间回复。
end


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

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

相关文章

Spring框架的概述及基本应用

Spring的基本应用 文章目录Spring的基本应用1. Spring 概述1.1 什么是Spring1.2 Spring 框架的优点1.3 Spring的体系结构2. Spring的核心容器2.1 BeanFactory2.2 ApplicationContext3. Spring的入门程序3.1 在pom下利用maven导入Spring所需要的jar包3.2 简单搭建起demo结构3.3 …

Java中数组的定义与使用(Java系列3)

目录 前言&#xff1a; 1.什么是数组 2.数组的创建 3.数组的初始化 4.数组的使用 5.数组是引用类型 6.基本类型变量与引用类型变量的区别 7.数组的应用 8.二维数组 结束语&#xff1a; 前言&#xff1a; 前面小编与大家分享了C语言与Java中的区别&#xff0c;还有一…

leaflet教程041: Point 和 LatLng 坐标互相转换

第041个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+leaflet中使用Point和LatLng,这里做了两者之间的转换。 注意 两者转换后的值,返回相对于原点像素的相应像素坐标或经纬度坐标。zoom改变,原点(地图图层左上角的投影像素坐标)的值会改变,所以获得的值也会变化。…

51单片机学习笔记1 简介及开发环境

51单片机学习笔记1 简介及开发环境一、51单片机1. STC89C52单片机简介2. 命名规则3. 封装&#xff08;1&#xff09;PDIP&#xff08;2&#xff09;LQFP&#xff08;3&#xff09;PLCC&#xff08;4&#xff09;PQFP二、STC8051结构1. STC 8051 内部结构图2. 内部结构框图3. 单…

Android设置TabLayout熟悉及下划线宽度

Tablayout的使用 属性 app&#xff1a;tabMod 设置Tab模式 app&#xff1a;tabTextColor 设置文本颜色 app&#xff1a;tabSelectedTextColor 设置选中文本颜色 app:tabIndicatorColor 设置下滑条颜色 app:tabMaxWidth“xxdp” 设置最大的tab宽度 app:tabMinWidth“xxdp” 设置…

牛客网之SQL100题(7)-字符串截取、切割、删除、替换

知识点&#xff1a; &#xff08;1&#xff09;substring_indexsubstring_index(str,delim,count) str:要处理的字符串 delim:分隔符 count:计数 &#xff08;2&#xff09;切割、截取、删除、替换 1 2 3 4 5 6 7 8 9 10 11 12 13 14 select -- 替换法 replace(string, 被…

类型转换C11

类型转换 C类型转换分为显式类型转换和隐式类型转换 &#xff0c;隐式类型转换由编译器自动完成&#xff0c;这里只讨论显式类型转换。 旧式风格的类型转换 type(expr); // 函数形式的强制类型转换 (type)expr; // C语言风格的强制类型转换现代C风格的类型转换 cast-name&l…

1-2 VMware安装Rocky9.0和Ubuntu22.04系统

文章目录前言下载链接VMware使用安装Rocky9.0系统Rocky初始化安装Ubuntu22.04系统Ubuntu初始化VMware快照前言 VMware虚拟机软件是一个“虚拟PC”软件&#xff0c;它使你可以在一台机器上同时运行二个或更多Windows、DOS、LINUX系统。 Rocky Linux 9.0 操作系统与2022年7月14…

基于matlab GUI的数字图像处理系统

目 录 摘 要 I Abstract II 第1章 绪论 1 1.1选题背景及意义 1 1.2国内外研究现状 2 1.2.1国内研究现状 2 1.2.2国外研究现状 3 1.3研究主要内容 3 第2章 数字图像处理系统设计 5 2.1设计概括 5 2.2文件 6 2.2.1打开 6 2.2.2保存 6 2.2.3退出 6 2.3图像变形 7 2.3.1图像缩放 7 …

Spring Cloud Gateway 使用示例

Spring Cloud Gateway 使用示例 作者&#xff1a; Grey 原文地址&#xff1a; 博客园&#xff1a;Spring Cloud Gateway 使用示例 CSDN&#xff1a;Spring Cloud Gateway 使用示例 说明 Spring Cloud Gateway 用于构建 API 网关&#xff0c;基于 Spring WebFlux。 在Spr…

【雷达通信】回波数据处理(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜…

【VRP问题】基于蚁群算法求解配送路径最短问题附matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

静态成员函数与回调函数

1. 静态成员函数 1.1 静态成员函数调用 如何代码块里的函数get_object_count是静态成员函数&#xff0c;对静态成员函数无论是通过类名还是通过对象或对象指针调用&#xff0c;最终都会被编译器转换为全局非成员函数的调用。例如obj.get_object_count()或Point3d::get_object…

BigDecimal精度丢失问题

浅谈BigDecimal精度丢失问题 文章目录浅谈BigDecimal精度丢失问题一. 简介二. 错误使用三. 原因分析四. 正确使用一. 简介 ​ Java在java.math包中提供的API类BigDecimal&#xff0c;用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数&#…

大数据Kudu(二):Kudu架构

文章目录 Kudu架构 一、​​​​​​​Kudu存储模型及概念 二、​​​​​​​​​​​​​​Kudu table存储原理 Kudu架构 一、​​​​​​​Kudu存储模型及概念 Kudu有自己的数据存储模型&#xff0c;不依赖于HDFS、Hive、HBase其他大数据组件。Kudu有自己的集群&#…

Oracle存储过程入门教程(通俗理解存储过程)

Oracle存储过程入门通俗介绍一、存储过程通俗理解二、创建存储过程基本语法(汇总)三、执行存储过程的方式&#xff08;5种&#xff09;四、网上现有的创建存储过程的两种方式解释&#xff08;看注释&#xff09;五、一些存储过程示例&#xff08;仅供参考&#xff09;六、其他语…

蒸馏+Distilling Knowledge via Knowledge Review论文笔记

文章目录一、前言二、蒸馏1.背景介绍2.知识蒸馏和迁移学习之间的区别3.Hinton提出的知识蒸馏Pipeline4.蒸馏的知识形式5.知识蒸馏的方法三、Distilling Knowledge via Knowledge Review论文笔记1.思想介绍2.Pipeline3.实验结果参考文献一、前言 近期在阅读cvpr 2021的一篇关于蒸…

通过Tomcat / Small Tomcat,如何部署Servlet?(超详细)

目录 基于Tomcat对Servlet进行部署 一、创建项目 二、引入Servlet依赖 三、构建目录结构 四、编写代码 五、打包程序 六、部署程序 七、验证程序 基于Smart Tomcat对Servlet进行部署 第一步&#xff1a;下载Smart Tomcat插件 第二步&#xff1a;进行相关配置 第三步…

【Unity3D】选中物体描边特效

1 前言 描边的难点在于如何检测和识别边缘&#xff0c;当前实现描边特效的方法主要有以下几种&#xff1a; 1&#xff09;基于顶点膨胀的描边方法 在 SubShader 中开 2 个 Pass 渲染通道&#xff0c;第一个 Pass 通道渲染膨胀的顶点&#xff0c;即将顶点坐标沿着法线方向向外扩…

Android BLE HIDS Data ,从问询DB 到写入Android 节点的flow 之一

BLE 的HIDS服务&#xff0c;可以理解为BR/EDR HID在BLE 上的简化版&#xff0c;因BLE的特殊性&#xff0c;BR/EDR HID的部分feature在HIDS 中被移除。 本文将讨论Android 蓝牙BLE 中HIDS 服务如何接收 Data 并写入到Android 节点"/dev/uhid"的flow。----关于Android…