[Linux入门]---Linux项目自动化构建工具-make/Makefile

目录

  • 1.背景
  • 2.make指令
    • 输入make默认为Makefile文件第一条指令执行
    • Makefile文件对gcc指令特殊处理及原理
    • 特殊符号
  • 3.总结

1.背景

  • 会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力
  • 一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作
  • makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
  • make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:DelphimakeVisual C++nmakeLinuxGNUmake。可见,makefile都成为了一种在工程方面的编译方法。
  • make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建。

2.make指令

我们使用vim编辑器创建了test.c文本文件编译了如下代码:

#include <stdio.h>
int main()
{
printf("hello Makefile\n");
return 0;
}

输入指令:

gcc -o mytest test.c//编译允许代码

Xshell演示结果如下:
在这里插入图片描述

这个编译运行可执行程序过程还算简单,那如果需要代码代码预处理、编译、汇编、链接生成可执行程序等等过程的时候,那么就需要输入如下指令:

gcc -E test.c -o test.i #预处理
gcc -S test.i -o test.s #编译
gcc -c test.s -o test.o #汇编
gcc test.o -o test #生成可执行程序
./test #找到对应路径下可执行程序运行

使用完之后,或者发生错误,需要删除文件

rm -rf test.i test.s test.o test

Xshell演示结果如下:
在这里插入图片描述

上面的指令输入一次还算简单,假设你的代码需要多次修改,就需要重复输入预处理、编译、汇编、链接、删除指令,会很麻烦!这时候我们就需要使用到Makefile文件/makefile文件(首字母m大小写都可以)。

使用vim编辑器创建Makefile文件,向里面编入如下指令

test:test.ogcc test.o -o test 
test.o:test.sgcc -c test.s -o test.o
test.s:test.igcc -S test.i -o test.s
test.i:test.cgcc -E test.c -o test.i
clean:rm -rf test test.o tes.s test.i

Xshell演示结果如下:
在这里插入图片描述
在这里插入图片描述

  • test:test.o为依赖关系,即test文件生成需要依赖于test.c文件该指令写在行首;gcc test.o -o test 为依赖方法,通过gcc指令处理test.o文件得到test文件,该指令前有一个tab键的空格;所以必须要有test.o文件,而test.o文件的生成依赖于test.s文件,test.s文件依赖于test.i文件,test.i文件依赖于test.c文件,依赖关系后面伴随着依赖(实现)方法,由此可以看出test文件需要依靠层层依赖关系以及依赖方法才能得到;(像递归一样)
  • ②而clean指令后面为空格,无依赖关系表明clean不依赖于任何文件、指令,同时有自己的依赖(实现)方法。

输入make默认为Makefile文件第一条指令执行

指令实现顺序如下:
在这里插入图片描述
只输入make指令:
在这里插入图片描述
指令实现顺序如下:
在这里插入图片描述
只输入make指令:
在这里插入图片描述

①只输入make指令,只会执行Makefile文件实现的第一条指令(从上到下),一般我们程序执行指令放在作为Makefile文件的第一条指令;其他指令通过make+Makefile指令/文件名实现!
②Makefile文件的各文件依赖关系指令可以在任意位置(不一定是从上到下),系统会在Makefile文件中找到得到目标文件需要实现的依赖方法,所以对应的依赖关系缺失会导致指令运行不起来!总而言之就是make会自动推导Makefile中的依赖关系(栈式结构)

Makefile文件对gcc指令特殊处理及原理

为什么进行编译拦截?
在这里插入图片描述

我们使用make指令对test文件进行多次编译运行,发现只有第一次make指令被执行了,再次输入make指令却不被执行!这是为什么呢?就像机器提示那样:test文件没有更新,所以不需要进行多次编译!为什么机器会对我们的多次编译的指令进行拦截呢?多次编译消耗时间,会使Linux机器的工作效率大大降低,我们现在之所以没有感受出来,是因为写的代码太少了,当程序代码量很大的时候,编译一次编译需要消耗几十分钟、几个小时甚至更久,我相信对同样的代码编译多次的行为,作为程序员的你是第一个不答应的!😾😾😾

怎么做到对相同源文件只做一次编译呢?
一般情况下是由源文件生成可执行文件(即先有源文件,才有可执行文件),所以源文件最近修改时间比可执行文件早(老)。如果我们更改了源文件,此时源文件的修改时间比旧的可执行文件晚,所以此时我们使用make指令就可以将修改后的源代码重新编译生成新的可执行文件。该过程是怎么样的呢?接下来让我们认识一条指令!
stat指令

语法:stat 选项 文件名
功能: 显示文件\文件系统的详细信息,包括文件的访问时间,文件内容修改时间,文件属性的修改时间。
在这里插入图片描述
Access:文件的访问时间,查看、修改文件内容都可以算访问,Access显示的时间更新;Modify:文件内容修改时间,只有对文件内容进行增删等修改文件内容操作,Modify时间更新;Change:文件属性的修改时间,文件大小、文件拥有者、文件所属组等文件属性修改,Change显示时间会被更新。②文件内容修改一次,Modify显示的时间会被更新;文件属性内容修改一次,Change显示的时间会被更新;因为平时我们访问文件的次数比较频繁,所以访问文件达到一定次数Access显示的时间才会被更新。③修改源文件内容而引起的时间变化,源文件是否被编译比较源文件和可执行文件的是Modify显示的时间。
在这里插入图片描述
在这里插入图片描述

使用touch指令更新时间

指令1: touch -a 文件名(使用该指令更新文件的Access显示的时间、Change显示的时间)
指令2: touch -m 文件名(使用该指令更新文件的Modify显示时间)
先使用touch -m 文件名更新源文件的Modify显示时间,然后使用make指令重新编译源文件!
在这里插入图片描述

特殊符号

在这里插入图片描述
使用特殊符号:
在这里插入图片描述
使用之后:
在这里插入图片描述

$@表示冒号左边的文件名,$^表示冒号右边的文件名,在Makefile文件可以使用@放在语句前进行注释!

使用.PHONY将目标文件成为伪目标
在这里插入图片描述
在这里插入图片描述

使用.PHONY可以将test指令(文件)变成伪目标,使该指令(文件)总是被执行!一般情况,我们将clean指令(文件)设置为伪目标!
在这里插入图片描述

3.总结

1make会在当前目录下找名字叫“Makefile”“makefile”的文件。
2. 如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“test”这个文件,并把这个文件作为最终的目标文件。
3. 如果test文件不存在,或是test所依赖的后面的test.o文件的文件修改时间要比test这个文件新,就会执行后面所定义的命令来生成test这个文件。
4. 如果test所依赖的test.o文件不存在,那么make会在当前文件中找目标为test.o文件的依赖性,如果找到则再根据那一个规则生成test.o文件。(这有点像一个堆栈的过程)
5. test.o的依赖方法存在,make会生成test.o文件,然后再用 test.o 文件声明make的终极任务,也就是执行test文件了。
6. make的依赖性:make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。
7. 在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make不执行。
8. make只管文件的依赖性,即,如果在make找到依赖关系之后,冒号后面的文件还是不在,make不执行
9.工程是需要被清理的,像clean这种指令没有被第一个目标文件直接或间接关联,那么它后面所定义的命令将不会被自动执行,可以显示要make执行。即命令——“make clean”,以此来清除所有的目标文件,以便重编译。
10.一般我们将clean的目标文件设置为伪目标,用 .PHONY 修饰伪目标的特性是,总是被执行的。
11.make指令会判定文件的新旧,判定是否需要重新进行执行依赖关系,进行编译!

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

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

相关文章

maven多模块依赖包程序包xxx不存在

背景 rpc-common 被 rpc-server、rpc-client依赖 项目地址 https://github.com/pjmike/springboot-rpc-demo mvn clean install 打包时报错 报错信息 程序包xxxx不存在 找不到符号 原因分析 原因还不清楚&#xff0c;网友们帮解答一下 解决 主pom.xml 添加 <packaging…

微调大型语言模型(一):为什么要微调(Why finetune)?

今天我们来学习Deeplearning.ai的在线课程 微调大型语言模型(一)的第一课&#xff1a;为什么要微调(Why finetune)。 我们知道像GPT-3.5这样的大型语言模型(LLM)它所学到的知识截止到2021年9月&#xff0c;那么如果我们向ChatGPT询问2022年以后发生的事情&#xff0c;它可能会…

LeetCode 刷题记录——从零开始记录自己一些不会的(二)

20. 替换后的最长重复字符 题意 给你一个字符串 s 和一个整数 k 。你可以选择字符串中的任一字符&#xff0c;并将其更改为任何其他大写英文字符。该操作最多可执行 k 次。 在执行上述操作后&#xff0c;返回包含相同字母的最长子字符串的长度。 思路 代码 class Solution…

API(十一) 获取openresty编译信息

一 ngx.config 说明&#xff1a; 不常用,了解即可 ngx.config.subsystem 说明&#xff1a; 用的四层还是七层代理 ngx.config.debug 说明&#xff1a; 返回的是boolean类型, openresty rpm安装一般没有 --with-debug编译选项对比&#xff1a; nginx rpm 安装一般携带 --wi…

【二叉树魔法:链式结构与递归的纠缠】

本章重点 二叉树的链式存储二叉树链式结构的实现二叉树的遍历二叉树的节点个数以及高度二叉树的创建和销毁二叉树的优先遍历和广度优先遍历二叉树基础oj练习 1.二叉树的链式存储 二叉树的链式存储结构是指&#xff0c;用链表来表示一棵二叉树&#xff0c;即用链来指示元素的逻辑…

Labelme分割标注软件

Labelme分割标注软件 1、环境配置与安装1.1 创建conda虚拟环境(建议)1.2 安装Labelme 2、简单使用2.1 创建label标签文件2.2 启动labelme2.3 打开文件/文件夹2.4 设置保存结果路径2.5 标注目标2.6 保存json文件格式 3 格式转换3.1 转换语义分割标签3.2 转换实例分割标签 相关重…

十四、MySql的用户管理

文章目录 一、用户管理二、用户&#xff08;一&#xff09;用户信息&#xff08;二&#xff09;创建用户1.语法&#xff1a;2.案例&#xff1a; &#xff08;三&#xff09; 删除用户1.语法&#xff1a;2.示例&#xff1a; &#xff08;四&#xff09;修改用户密码1.语法&#…

公司内部网段太多,管控混乱,该如何规范跨网文件传输交换?

在当今的信息化时代&#xff0c;文件传输交换是企业日常工作中不可或缺的一项功能。无论是内部员工之间&#xff0c;还是与外部合作伙伴之间&#xff0c;都需要频繁地进行文件的发送、接收、共享和协作。然而&#xff0c;由于企业内部网段的复杂性和多样性&#xff0c;以及数据…

【TCP】三次握手 与 四次挥手 详解

三次握手 与 四次挥手 1. 三次握手2. 四次挥手三次握手和四次挥手的区别 在正常情况下&#xff0c;TCP 要经过三次握手建立连接&#xff0c;四次挥手断开连接 1. 三次握手 服务端状态转化&#xff1a; [CLOSED -> LISTEN] 服务器端调用 listen 后进入 LISTEN 状态&#xff…

input修改checkbox复选框默认选中样式

问题描述&#xff1a; <input type"checkbox" /> input修改checkbox默认选中样式&#xff0c;直接设置选中后的样式不生效&#xff0c;需要先给复选框设置-webkit-appearance: none&#xff08;取消默认样式&#xff09;&#xff0c; 再设置样式才会生效。 …

【lesson9】进程

文章目录 什么是进程如何管理进程查看进程创建子进程 什么是进程 我们用一张Windows下的任务管理器图来辅助我们观看&#xff0c;我们一个可以看到应用在运行的时候就是一个个进程。 所以我们启动了一个软件本质上就是启动了一个进程。 在Linux下运行一条命令&#xff0c;./XXX…

数据结构——单链表

目录 一.前言 二.链表表示和实现&#xff08;单链表&#xff09; 1.1 顺序表的优缺点 1.2 链表的概念及结构 1.3 打印函数 1.4 空间函数 1.5 尾插函数&#xff08;最最最麻烦的&#xff09; 1.5.1 尾插最关键部分&#xff01; 1.6 头插函数 1.7 尾删函数…