【Linux基础】如何编写Makefile文件?


前言

   我们刚开始在Linux系统下进行编程时,采用的编译方法为:将程序所引用的文件打包成静态库/共享库,再使用生成的静态库/共享库与源程序一起编译成可执行文件
   然而,我们发现在一个中大型的C/C++工程中,往往包含了成百上千个源文件。如果我们使用上述方法编译,编译命令就会变得十分冗长,在输入命令的过程中容易出错。即便是正确输入了编译命令,在进行编译过程中,也会耗费较长的编译时间。显然,手动编译并不适用于大部分的Linux编程场景。
   为解决以上问题,我们将在本篇中学习如何编写Makefile文件完成自动化编译。


一、make工具简介

   在学习编写Makefile文件之前,我们需要先了解Linux系统中一个非常重要的编译命令make

1.什么是make?

   make是用于自动编译,链接程序的实用工具。它最主要最基本的功能就是通过makefile文件来描述源程序之间的相应关系,并自动维护编译工作。
   使用make工具的好处在于,在编译完成之后,若修改了某个源代码,make只对修改后的部分进行编译,其他目标文件不会更改,并且会安装文件依赖性来更新执行文件。大大提高了编译效率。

2.如何安装make?

  (1)进入root权限,终端命令:sudo su

  (2)进入更新列表,终端命令:apt-get update

  (3)Linux安装make,终端命令:apt-get install ubuntu-make

  (4)验证是否安装成功,终端命令:make -v,显示所安装make的版本号即安装成功。

二、编写Makefile文件

1.文件组成

  • makefile三要素:targets(目标),prequisities(依赖),command(命令)
  • 每个依赖关系由一个目标文件和一组该目标所需的源文件(依赖文件)构成。
  • 命令则描述了如何通过这些依赖关系文件创建目标。

makefile文件格式如下:
             目标文件:依赖文件
             [tab键] gcc -o 目标文件 依赖文件

2.工作原理

  • 目标生成:检查规则中的依赖是否存在,若依赖文件不存在,则寻找是否有规则生成依赖文件。
  • 目标更新:检查目标文件的所有依赖文件,任何一个依赖文件有更新时,就重新生成目标文件。

3.Makefile文件优点

(1)减少重复编译时间

   在改动其中一个文件时,能判断哪些文件被修改过,只对该文件进行重新编译,然后重新链接所有目标文件, 大大提高了编译效率,节省了编译时间。

(2)利于大量代码关系维护

   中大型工程中源代码较多,手工维护编译时间长,且编译命令复杂,把代码维护命令和编译命令写在makefile文件中,然后再用make工具解析此文件自动执行相应命令,实现高效编译。

4.单级目录下的Makefile文件编写

(1)第一版本,通俗易懂但不通用

在这里插入图片描述

(2)第二版本,变量obj类似C/C++中的宏定义,进行等量替换

在这里插入图片描述

(3)第三版本,将依赖文件改成相应的头文件,make命令在编译过程中会自动推导

在这里插入图片描述

(4)第四版本,$@目标文件;$^所有依赖文件;$<第一个依赖文件

在这里插入图片描述

(5)第五版本,wildcard函数,查找文件下所有文件名;patsubst函数,查找替换

在这里插入图片描述

5.多级目录下的Makefile文件编写

   当工程文件比较大时,我们可以采用文件分类的方式,将工程文件分为头文件(include)源文件(src)目标文件(obj)可执行文件(bin),并在这几个文件的同级目录下编写makefile文件,如下图所示。

在这里插入图片描述

此时,对应的makefile文件通用写法,如下所示。

DIR_INC = ./include
DIR_SRC = ./src
DIR_OBJ = ./obj
DIR_BIN = ./bin

SRC = $(wildcard ${DIR_SRC}/*.c)
OBJ = $(patsubst %.c,${DIR_OBJ}/%.o,$(notdir ${SRC}))

TARGET = main

BIN_TARGET = ${DIR_BIN}/${TARGET}

CC = gcc
CFLAGS = -g -Wall -I${DIR_INC}

${BIN_TARGET}:${OBJ}
	$(CC) $(OBJ)  -o $@

${DIR_OBJ}/%.o:${DIR_SRC}/%.c
	$(CC) $(CFLAGS) -c  $< -o $@

clean:
	find ${DIR_OBJ} -name *.o -exec rm -rf {} \;

总结

   以上就是关于如何编写Makefile文件的所有内容,希望大家阅读后都能有所收获!原创不易,转载请标明出处,若文章出现有误之处,欢迎读者留言指正批评!

在这里插入图片描述

  • 16
    点赞
  • 73
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
概述 什么是 makefile?或许很多Windows 的程序员都不知道这个东西,因为那些Windows 的IDE 都为你做了这个工作,但我觉得 要作一个好的和professional 的程序员,makefile 还是要懂。这就好像现在有这么多的HTML 的编辑器,但如果你想成为一个专 业人士,你还是要了解HTML 的标识的含义。特别在Unix 下的软件编译,你就不能不自己写makefile 了,会不会写makefile, 从一个侧面说明了一个人是否具备完成大型工程的能力。 因为,makefile 关系到了整个工程的编译规则。一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中, makefile 定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复 杂的功能操作,因为makefile 就像一个Shell 脚本一样,其中也可以执行操作系统的命令。 makefile 带来的好处就是——“自动化编译”,一旦写好,只需要一个make 命令,整个工程完全自动编译,极大的提高了软件 开发的效率。make 是一个命令工具,是一个解释makefile 中指令的命令工具,一般来说,大多数的IDE 都有这个命令,比如: Delphi 的make,Visual C++的nmake,Linux 下GNU 的make。可见,makefile 都成为了一种在工程方面的编译方法。 现在讲述如何写 makefile 的文章比较少,这是我想写这篇文章的原因。当然,不同产商的make 各不相同,也有不同的语法, 但其本质都是在“文件依赖性”上做文章,这里,我仅对GNU 的make 进行讲述,我的环境是RedHat Linux 8.0,make 的版本 是3.80。必竟,这个make 是应用最为广泛的,也是用得最多的。而且其还是最遵循于IEEE 1003.2-1992 标准的(POSIX.2)。 在这篇文档中,将以C/C++的源码作为我们基础,所以必然涉及一些关于C/C++的编译的知识,相关于这方面的内容,还请各 位查看相关的编译器的文档。这里所默认的编译器是UNIX 下的GCC 和CC。 关于程序的编译和链接

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孤生i

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值