专栏首页howtouselinuxmakefile介绍 通俗易懂

makefile介绍 通俗易懂

Make 概述

在学习Makefile之前,首先介绍一下make命令,make命令是GNU的工程化编译工具,它用于编译大量互相关联的源代码,使用它可以实现项目的工程化管理,提高开发效率。

Make 可自动决定一个大程序中哪些文件需要重新编译,并发布重新编译它们的命令。Make的使用不仅限于程序,它可以适用于任何如果一些文件变化导致另外一些文件必须更新的任务。

当然,我们要想使用Make命令,必须先写一个称为Makefile的文件,该文件描述程序中各个文件之间的相互关系,并且提供每一个文件的更新命令。

关于编译和链接

编译:生成目标文件(编译时,编译器需要的是语法的正确,函数与变量的声明的正确)

链接:生成可执行文件(链接时,主要是链接函数和全局变量,把目标文件链接成应用文件)

Windows程序开发一般包括:编辑、编译链接、执行三大步骤。

嵌入式程序开发一般包括:

1、编辑

2、指定链接地址

3、指定连接顺序

4、编译链接

5、执行(烧写到单板再启动)

Linux程序开发一般包括:

1、编辑

2、链接脚本

3、用命令行链接文件顺序

4、运行命令行

5、执行(烧写到单板再启动)

通常我们把上述的2、3、4条内容写入到Makefile文件中,然后执行Make完成编译。

Makefile文件介绍

Make程序需要一个所谓的Makefile文件来告诉它干什么。通常情况下,Makefile文件告诉Make源代码文件之间的链接关系、依赖关系等从而准确编译和链接成一个应用程序。

这里举一个简单的例子,假设我们把5个C源程序文件和3个头文件编译和连接成为一个FY的目标程序。我们需要写一个Makefile文件来告诉Make怎样运行所需要的杂乱无章的命令。

如果这个工程从没被编译过(没有编译后生成的目标文件),那么所有的.c源文件都要被编译并链接。

如果有编译后的目标文件,但此工程的某几个.c源文件被修改了,那么我们只编译被修改的.c文件,并链接目标程序。

如果有编译后的目标文件,但此工程的头文件被改变了,那么需要编译引用了这几个头文件的.c文件,并链接目标程序。

通过上面的这些规则,避免了每次Make都去重新编译或者链接。只要写好Makefile,无论怎么修改源程序,只要运行下Make命令就自动完成编译和链接,大大提高了项目运行开发的效率。

Understanding Makefile With Examples

Makefile的规则

一个简单的Makefile文件包含一系列的“规则”,其样式如下:

目标: 依赖1 依赖2…

<‘tab>命令

目标:通常是要产生的文件的名称,它可以是可执行文件(OBJ文件),也可是一个执行的动作名称,如‘clean’。

依赖:用来输入从而产生目标的文件,一个目标经常有几个依赖。

命令:Make执行的动作,一个规则可以含有几个命令,每个命令占一行。

注意:每个命令行前面必须是一个Tab字符,即命令行第一个字符是Tab。这是不小心容易出错的地方。

以下是写好的Makefile文件,他告诉Make把源程序编译链接成一个FY的目标文件。

使用Makefile文件创建可执行的称为‘FY’的文件,键入:make

使用Makefile文件从目录中删除可执行文件和目标,键入:make clean

在这个Makefile文件例子中:

目标包括可执行文件‘FY’和OBJ文件‘main.o’、‘kdb.o’等。

依赖是C语言源文件和C语言头文件如‘main.c’和‘defs.h’等。事实上,每一个OBJ文件既是目标也是依赖。

命令行包括‘gcc -c main.c’和‘cc -c kbd.c’等(缩进一定要以一个Tab键作为开头)。

make是如何工作的

在编译过程中,我们通常只是输入一个make命令,那它到底是怎么运行工作呢?

首先make会在当前目录下查找名称为“Makefile”或者“makefile”的文件。

找到文件之后,它会继续找文件中注明的第一个目标文件(即上文的FY)。

如果目标文件(FY)不存在,或者目标文件后的依赖文件(.o文件)的修改时间要比目标文件(FY)新,那么,它继续寻找后面定义的命令。

如果目标文件FY依赖的.o文件存在,那么make会在当前文件中寻找目标为.o文件的依赖性。若找到则根据规则继续生成一个头文件。

make会根据文件夹内的.c或者.h生成.o文件,然后再用.o文件生成FY可执行的程序。

注:make只会检查文件依赖,不会对命令进行检查。所以命令写错了是不会报错的。

使用变量简化makefile文件

在例子中,我们在‘FY’的生成规则中把所有的OBJ文件列举了两次

如果我们在FY项目中又新加入了一个.c文件,那么Makefile需要好几处都做改动。而且如果项目大的话Makefile也会写的很混乱,不方便阅读,出错的概率也更大。因此,我们需要一个变量来代替我们写的这些文件。

比如声明一个变量objects(其它名字也可以)来表示这一大串.o文件,然后,在每一个需要列举OBJ文件的地方,我们使用写为`$(objects)'形式的变量代替。

使用变量后的完整的makefile文件:

这样如果有新的文件,只用修改一下objects,给它添加一个文件即可。

让make自动推导命令

make具有识别并且自动推导命令的能力,它识别出一个.o文件,就会自动将其对应的.c文件加在依赖关系中。并且也会自动推导出相关的编译命令。所以我们可在依赖中省略C语言源程序,进而可以省略命令,实现Makefile文件编写更加简洁。

这种方式称为make的隐晦规则。.PHONY表示clean是一个伪目标文件。

另一种风格的makefile文件

make可以自动推导命令,这很方便。但是Makefile的每个.o文件都依赖于很多的.h文件,能不能把这些.h文件综合到一起呢?

看一下这种书写方式:

这里的defs.h是所有OBJ文件的共同的一个依赖;command.h和bufffer.h是具体列出的OBJ文件的共同依赖。

目录中删除文件的规则

对于编写习惯的养成而言,我们最好在每个Makefile中都写一个清空目标文件的clean命令,这样有利用重新编译。例如:

在实际应用中,应该编写较为复杂的规则以防不能预料的情况发生。更接近实用的规则样式如下:这样可以防止make因为存在名为’clean’的文件而发生混乱,并且导致它在执行rm命令时发生错误

注意,后者的-表示忽略问题,强制执行。而且不要将clean放在文件的开头,因为Makefile默认执行的就是文件开头的target。因此,对于clean,最好将它放在文件最后。

————————————————

Understanding Makefile With Examples

原文链接:https://www.howtouselinux.com/post/understanding-makefile-with-examples

相关文章

  • 对spark中RDD的partition通俗易懂的介绍

    我们要想对spark中RDD的分区进行一个简单的了解的话,就不免要先了解一下hdfs的前世今生。

    飞叔Brother
  • Adaboost入门教程——最通俗易懂的原理介绍

    Adaboost算法基本原理就是将多个弱分类器(弱分类器一般选用单层决策树)进行合理的结合,使其成为一个强分类器。

    机器学习AI算法工程
  • 通俗易懂DenseNet

    在博客《ResNet详解与分析》中,我们谈到ResNet不同层之间的信息流通隐含在“和”中,所以从信息流通的角度看并不彻底,相比ResNet,DenseNet最...

    李拜六不开鑫
  • PID通俗易懂

    很多同学都不清楚 PID 是个什么东西,因为很多不是自动化的学生。他们开口就要资料,要程序。这是明显的学习方法不对,起码,首先,你要理解 PID 是个什么东西。...

    morixinguan
  • 通俗易懂的生产环境Web应用架构介绍

    看见一篇非常通俗易懂且适合新手阅读的Web应用架构文章,我将其手工翻译了出来,分享给大家。

    蛮三刀酱
  • 通俗易懂的生产环境Web应用架构介绍

    看见一篇非常通俗易懂且适合新手阅读的Web应用架构文章,我将其手工翻译了出来,分享给大家。

    Rude3Knife的公众号
  • 通俗易懂 empowered RL

    Inspired by examples from the animal kingdom, social sciences and games the ...

    用户1908973
  • 通俗易懂讲解WebSocket

    什么是WebSocket WebSocket是一种网络协议,在OSI模型中,WebSocket协议与HTTP协议一样,都属于最顶层的应用层协议。有些朋友可能会有...

    Bug开发工程师
  • 通俗易懂 | SVM的HingeLoss

    在学这个之前,如果你已经学过了逻辑回归,那就更好了。一文搞懂:线性回归与逻辑回归(似然参数估计)

    机器学习炼丹术
  • C++中使用CMake编译管理项目

    CMake是一个跨平台的Makefile生成工具,可以根据特定的规则生成相应的Makefile文件,并对C/C++源代码进行编译和管理。 有一篇博客介绍CMa...

    ccf19881030
  • CMake的使用

    CMake是一个跨平台的Makefile生成工具,可以根据特定的规则生成相应的Makefile文件,并对C/C++源代码进行编译和管理。 有两篇博客介绍CMa...

    ccf19881030
  • 通俗易懂的HTTPS解释

    我们在网络的行为(例如看文章、购物、上传图片),简单来说都是向服务器发送消息、接收服务器的消息,这个过程很像信鸽传书。

    dys
  • Build/Host/Target 通俗易懂 的 解释

    According to the GNU convention, there are three platforms involved in the softw...

    望天
  • [ 物联网篇 ] 02 - Yocto Project (YP)快速入门

    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/z2066411585/article/details...

    程序手艺人
  • 通俗易懂理解Attention机制

    在Encoder-Decoder结构中,Encoder把所有的输入序列都编码成一个统一的语义特征c再解码,因此, c中必须包含原始序列中的所有信息,它的长度就成...

    zenRRan
  • Javascript闭包剖析(通俗易懂)

    Marser
  • 通俗易懂的Redux了解下

    Redux让我脑仁疼,感觉搞不定他。因为Redux对我而言太抽象了,所以我用通俗易懂地方法去思考Redux,感觉能够理解Redux一些了。

    小美娜娜
  • 通俗易懂PHP基础【1-HelloWord】

    PHP是一门非常好上手的编程入门语言,本系列《通俗易懂PHP》宗旨就是让新手小白,低成本、低耗时的学习PHP编程基础语法。如果,您已经是位有经验的PHP可以略过...

    Lemon黄
  • 通俗易懂设计模式解析——中介者模式

      今天我们一起看看中介者模式,怎么去理解这个模式呢?说起来也简单、好理解。生活中我们租房经常都是通过中介来实现的。一般租房要么是房东直租要么是中介。那么今天要...

    小世界的野孩子

扫码关注云+社区

领取腾讯云代金券