Linux   发布时间:2022-03-31  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了GNU make(一):GNU make概述大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
@H_450_2@

概述

一、GNU make概述 1. GNU make是什么? GNU make是Linux环境下著名的工程构建和管理工具,使得我们可以使用一个命令就完成编译、链接以至于执行,自动地帮我们完成构建工作。目前,大量的C/C++项目使用make作为工程构建工具,大量的IDE使用与make相同的工程构建策略。 2. GNU make如何工作? Make的本质是一个解释器,用于解释一种名为Makefile的脚本
@H_450_2@
@H_450_2@ @H_450_2@
@H_450_2@

一、GNU make概述

@H_944_20@1. GNU make是什么?

GNU make是Linux环境下著名的工程构建和管理工具,使得我们可以使用一个命令就完成编译、链接以至于执行,自动地帮我们完成构建工作。目前,大量的C/C++项目使用make作为工程构建工具,大量的IDE使用与make相同的工程构建策略。

2. GNU make如何工作?

@H_743_23@make的本质是一个解释器,用于解释一种名为@H_437_26@makefile的脚本。这个Makefile脚本告诉make以何种方式编译源代码链接程序。从本质上来看,@H_743_23@make通过比较相关文件的最后修改时间,来决定哪些文件需要更新,哪些文件不需要更新,之后执行以下操作:

  • 对于那些需要更新的文件,make就使用在Makefile中预定义的命令来重新构建这些文件
  • 对于那些无需更新的文件,make就什么也不做。

二、Makefile简介

编写Makefile脚本是一项相对复杂的工作,它有自己的书写格式、关键字函数而且,在Makefile脚本中可以使用宿主操作系统所提供的任何SHell命令来完成想要完成的操作。

1. Makefile的规则介绍

在Makefile中,规则是最重要的组成部分,通过定义一条或多条规则来描述文件如何被生成。Makefile一个最基本的Makefile规则如下所示:

# 这里是单行注释。
Target : Pre[1] Pre[2] ... Pre[n]; Command[0]
    Command[1]
    Command[2]
    ...
    Command[M]

其中所包含的主要成员如下:

  • Target规则的目标。它通常是以下两种内容

  • Pre规则的依赖。它通常是以下两种内容

    • 生成目标所需要的文件名列表
    • 生成目标所需要的其他目标列表
    • 以上两种情况的杂揉
  • command规则的命令行。指的是为了生成目标所需要执行的SHell指令,可以出现在以下为止:

    • 在所有的依赖后面添加一个"",然后写命令。
    • 从目标和依赖所出现的下一行开始,以【TAB】键开头,然后编写多条命令。
  • 注释:和其他脚本相同,使用"#"作为注释的标志。

在所有的规则中,认的第一个规则的目标为最终目标,也就是make生成的目标;如果第一个规则是一个多目标规则,那么第一个目标被作为最终目标。

当然,Makefile中通常还包含了除了规则之外的很多东西(后续我们来展开讨论)。但无论它怎样复杂,它都符合以上介绍的最基本的格式

2. make如何解释规则

(1) make判断需要生成目标的依据

当make进行维护工作时,它按照如下顺序检查是否需要生成目标:

  1. 目标不存在,就生成它;
  2. 目标存在,但在目标的所有依赖中,至少存在一个依赖,在时间戳上比当前的目标更新 (这表明在上一次维护后,依赖被修改了),重新生成它;
  3. 什么也不做。

同时,对于规则,make还具有以下特性:

  1. 如果目标不是一个文件,并且没有依赖或者命令,那么它的时间戳被认为是最新的(确保它一定被执行)
  2. 如果一个目标不是最终目标的依赖,那么即便它被定义了,也不会被执行。

(2) make维护的抽象数据结构

当make解释器发现了一条规则时,它将按照顺序读取其目标、依赖和所有命令,然后维护一个数据结构来存储它们。这个数据结构的实现各有不同,但是为了帮助理解上面的特性,我们可以按照下面的样子来抽象并理解它:

GNU make(一):GNU make概述

其中,所有的依赖和目标组成了一个循环链表,而所有的命令是一个单链表。当make发现需要维护一个目标时,它将进行以下工作:

  1. 如果这个目标不存在,就生成它;

  2. 如果这个目标存在,就从第一个依赖开始顺序检查所有依赖,

  • 如果当前依赖是一个文件,那么检查它的时间戳来判定是否重新生成
  • 如果当前依赖是一个目标,那么寻找这个"依赖目标"的数据结构,并尝试维护它(将这个依赖作为目标,递归地进行工作)。

3. 如何执行make

在终端执行@H_369_240@make命令即可。当执行make命令时,有几个可选项:

  • -f:指定Makefile的文件名。
  • 目标名:将这个目标作为最终目标。

如果没有使用-f选项,那么make程序执行认的缺省选择:

  • @H_743_23@makefile
  • @H_743_23@makefile(推荐使用,因为能够和README、changelist文件放在一起)

三、编写一个最简单的HelloWorld脚本

作为HelloWorld脚本,它应该尽可能地简单。因此,我们不生成任何文件,仅仅让其在终端输出字符串即可。

【示例】一个最简单的Makefile脚本

# Makefile
HelloWorld:
    echo "Hello,world"

在这个Makefile脚本中,我们仅编写了一条规则:HelloWorld,它不具有任何依赖,并且只有一条命令:echo "Hello,world"。当Make解释器在解释这个脚本时,它将开始如下的工作:

  1. 读取这个脚本文件
  2. 构建所有规则的数据结构;
  3. 找到最终目标HelloWorld
  4. 发现HelloWorld目标在当前文件系统中不存在(也就不是一个文件,并且没有依赖,因此一定被执行。
  5. 执行命令:echo "Hello,world"

【运行结果】

[[email protected] 0000]$ make
echo "Hello,world"
Hello,world
[[email protected] 0000]$ make -f Makefile
echo "Hello,world
[[email protected] 0000]$ make HelloWorld
echo "Hello,world
[[email protected] 0000]$ make -f Makefile HelloWorld
echo "Hello,world

四、使用make来编译代码

【示例】使用make来维护代码

/*
 * foo.h
 */
#ifndef _foo_H_
#define _foo_H_

void foo();

#endif
/*
 * foo.c
 */
#include <stdio.h>
#include "foo.h"

void foo()
{
        printf("Hello,makefile\n");
}
/*
 * main.c
 */
#include "foo.h"

int main(int argc,char *argv[])
{
        foo();
        return 0;
}
# Makefile
HelloMakefile.elf: main.o foo.o
        gcc -o HelloMakefile.elf main.o foo.o
                
main.o: main.c
        gcc -c main.c -o main.o

foo.o: foo.c
        gcc -c foo.c -o foo.o

【运行结果】

[[email protected] 0000]$ ls
foo.c  foo.h  main.c  Makefile
[[email protected] 0000]$ make
gcc -c main.c -o main.o
gcc -c foo.c -o foo.o
gcc -o HelloMakefile.elf main.o foo.o
[[email protected] 0000]$ ls
foo.c  foo.h  foo.o  HelloMakefile.elf  main.c  main.o  Makefile
[[email protected] 0000]$ ./HelloMakefile.elf 
Hello,makefile
@H_450_2@
@H_450_2@
@H_450_2@@H_450_2@

大佬总结

以上是大佬教程为你收集整理的GNU make(一):GNU make概述全部内容,希望文章能够帮你解决GNU make(一):GNU make概述所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。