目录

  • makefile文件定义
  • makefile编写规则
    • makefile基本规则三要素:
    • makefile工作原理
    • 第二个版本的makefile
    • makefile的变量
      • 普通变量
      • 自带变量
      • 自动变量
    • 模式规则
    • makefile函数
      • wildcard函数
      • patsubst函数
    • makefile的清理操作
    • makefile第5个版本
    • makefile例子

makefile文件定义

makefile文件中定义了一系列的规则来指定, 哪些文件需要先编译, 哪些文件需要后编译, 哪些文件需要重新编译, 甚至于进行更复杂的功能操作, 因为makefile就像一个Shell脚本一样, 其中也可以执行操作系统的命令. makefile带来的好处就是——“自动化编译”, 一旦写好, 只需要一个make命令, 整个工程完全自动编译, 极大的提高了软件开发的效率。

make是一个命令工具, 是一个解释makefile中指令的命令工具, 一般来说, 大多数的IDE都有这个命令, 比如:Visual C++的nmake, Linux下GNU的make. 可见, makefile都成为了一种在工程方面的编译方法.
makefile文件中会使用gcc编译器对源代码进行编译, 最终生成可执行文件或者是库文件。

makefile文件的命名:makefile或者Makefile。

makefile编写规则

makefile由一组规则组成,规则如下:

目标: 依赖
(tab)命令

记得,命令的前面是tab键,不是空格!!!

makefile基本规则三要素:

目标:要生成的目标文件
依赖:目标文件由哪些文件生成
命令:通过执行该命令由依赖文件生成目标

下面以具体的例子来讲解:
当前目录下有main.c fun1.c fun2.c sum.c, 根据这个基本规则编写一个简单的makefile文件, 生成可执行文件main.

第一个版本的makefile:

main:main.c fun1.c fun2.c sum.cgcc -o main main.c fun1.c fun2.c sum.c -I./

缺点: 效率低, 修改一个文件, 所有的文件会全部重新编译。

makefile工作原理

若想生成目标, 检查规则中的所有的依赖文件是否都存在:
如果有的依赖文件不存在, 则向下搜索规则, 看是否有生成该依赖文件的规则:
如果有规则用来生成该依赖文件, 则执行规则中的命令生成依赖文件;
如果没有规则用来生成该依赖文件, 则报错.

如果所有依赖都存在, 检查规则中的目标是否需要更新, 必须先检查它的所有依赖,
依赖中有任何一个被更新, 则目标必须更新.(检查的规则是哪个时间大哪个最新)

若目标的时间 > 依赖的时间, 不更新
若目标的时间 < 依赖的时间, 则更新


总结:

  • 分析各个目标和依赖之间的关系
  • 根据依赖关系自底向上执行命令
  • 根据依赖文件的时间和目标文件的时间确定是否需要更新
  • 如果目标不依赖任何条件, 则执行对应命令, 以示更新(如:伪目标)

第二个版本的makefile

main:main.o fun1.o fun2.o sum.ogcc -o main main.o fun1.o fun2.o sum.o
main.o:main.cgcc -o main.o -c main.c -I./
fun1.o:fun1.cgcc -o fun1.o -c fun1.c
fun2.o:fun2.cgcc -o fun2.o -c fun2.c
sum.o:sum.cgcc -o sum.o -c sum.c

缺点: 冗余, 若.c文件数量很多, 编写起来比较麻烦。

makefile的变量

在makefile中使用变量有点类似于C语言中的宏定义, 使用该变量相当于内容替换, 使用变量可以使makefile易于维护, 修改起来变得简单。
makefile有三种类型的变量:

普通变量
自带变量
自动变量

普通变量

变量定义直接用 =
使用变量值用 $(变量名)

如:下面是变量的定义和使用
foo = abc          // 定义变量并赋值
bar = $(foo)       // 使用变量, $(变量名)

定义了两个变量: foo、bar, 其中bar的值是foo变量值的引用。

自带变量

除了使用用户自定义变量, makefile中也提供了一些变量(变量名大写)供用户直接使用, 我们可以直接对其进行赋值:

CC = gcc #arm-linux-gcc
CPPFLAGS : C预处理的选项 -I
CFLAGS:   C编译器的选项 -Wall -g -c
LDFLAGS :  链接器选项 -L  -l

自动变量

$@ 表示规则中的目标
$^ 表示规则中的所有条件, 组成一个列表, 以空格隔开, 如果这个列表中有重复的项则消除重复项
$< 表示规则中的第一个条件
$? 第一变化的依赖

特别注意:自动变量只能在规则的命令中使用.

模式规则

至少在规则的目标定义中要包含%, %表示一个或多个, 在依赖条件中同样可以使用 %, 依赖条件中的 %的取值取决于其目标:
比如: main.o:main.c fun1.o: fun1.c fun2.o:fun2.c, 说的简单点就是: xxx.o:xxx.c
makefile的第三个版本:

target=main
object=main.o fun1.o fun2.o sum.o
CC=gcc
CPPFLAGS=-I./$(target):$(object)$(CC) -o $@ $^%.o:%.c$(CC) -o  $@ -c $< $(CPPFLAGS)

makefile函数

makefile中的函数有很多, 在这里给大家介绍两个最常用的。

wildcard函数

wildcard – 查找指定目录下的指定类型的文件
src=$(wildcard *.c)  //找到当前目录下所有后缀为.c的文件,赋值给src

patsubst函数

patsubst – 匹配替换
obj=$(patsubst %.c,%.o, $(src)) //把src变量里所有后缀为.c的文件替换成.o

在makefile中所有的函数都是有返回值的。
当前目录下有main.c fun1.c fun2.c sum.c

src=$(wildcard *.c) 等价于src=main.c fun1.c fun2.c sum.c
obj=$(patsubst %.c,%.o, $(src))等价于obj=main.o fun1.o fun2.o sum.o

makefile的第四个版本:

src=$(wildcard  ./*.c)
object=$(patsubst %.c,%.o,$(src))
target=main
CC=gcc
CPPFLAGS=-I./$(target):$(object)$(CC) -o $@ $^%.o:%.c$(CC) -o  $@ -c $< $(CPPFLAGS)

缺点: 每次重新编译都需要手工清理中间.o文件和最终目标文件

makefile的清理操作

用途: 清除编译生成的中间.o文件和最终目标文件
make clean 如果当前目录下有同名clean文件,则不执行clean对应的命令, 解决方案:

  • 伪目标声明:
.PHONY:clean

声明目标为伪目标之后, makefile将不会检查该目标是否存在或者该目标是否需要更新

  • clean命令中的特殊符号:

-此条命令出错,make也会继续执行后续的命令。如:-rm main.o
rm -f: 强制执行, 比如若要删除的文件不存在使用-f不会报错

  • 其它

make 默认执行第一个出现的目标, 可通过make dest指定要执行的目标
make -f-f执行一个makefile文件名称, 使用make执行指定的makefile: make -f mainmak

makefile第5个版本

makefile的第5个版本:

src=$(wildcard  ./*.c)      # 等价于src=main.c fun1.c fun2.c sum.c,其中wildcard - 查找指定目录下的指定类型的文件
object=$(patsubst %.c,%.o,$(src))  # 等价于obj=main.o fun1.o fun2.o sum.o,其中,patsubst – 匹配替换
target=main
CC=gcc
CPPFLAGS=-I./$(target):$(object)$(CC) -o $@ $^%.o:%.c$(CC) -o  $@ -c $< $(CPPFLAGS).PHONY:clean
clean:-rm -f $(target) $(object)

在makefile的第5个版本中, 综合使用了变量, 函数, 模式规则和清理命令,
是一个比较完善的版本.

makefile例子

#2020-8-3# wildcard可以进行文件匹配
# patsubst 内容的替换#makefile的变量
# $@  代表目标
# $^ 代表全部依赖
# $< 第一依赖
# $? 第一变化的依赖#get all .c files
SrcFiles=$(wildcard *.c)
#all .c  files -->  .o   files
ObjFiles=$(patsubst %.c,%.o,$(SrcFiles))all:app#目标文件用法$(var)
# gcc前面要用Tab键,可以用vim敲入
app:$(ObjFiles)gcc -o $@ -I ./include $(ObjFiles)#模式匹配规则,$@,$< 这样的变量,只能在规则中出现
%.o:%.cgcc -c $<  -I./include -o $@test:@echo $(SrcFiles)@echo $(ObjFiles)#定义伪目标,防止有歧义
.PHONY:clean all#  "-@rm -f *.o" 减号的作用是当指令报错的时候依然执行,@的作用是不输出指令。clean:-@rm -f *.o-@rm -f app

参考
linux下开发之makefile文件

makefile编写规则相关推荐

  1. 一篇文章看懂makefile编写规则

    该篇文章为转载,是对原作者系列文章的总汇加上标注. 支持原创,请移步陈浩大神博客:(最原始版本) http://blog.csdn.net/haoel/article/details/2886 我转自 ...

  2. 【整理】Makefile编写规则

    Makefile 文章目录 Makefile Makefile的规则 语法 通配符 文件搜寻 伪目标 多目标 静态变量 自动生成依赖性 书写命令 嵌套执行make 定义命令包 变量使用 变量基础 变量 ...

  3. Makefile 编写入门

    Makefile编写规则: 刚开始跟这些Makefile的时候发现会报错误Makefile:2: missing separator. Stop. 在make命令后出现这种错误提示,是提示第2行没有分 ...

  4. Makefile文件的编写规则

    欢迎大家关注笔者,你的关注是我持续更博的最大动力 Makefile文件编写规则 文章目录: 1 makefile文件介绍 2 makefile文件编写 1 makefile文件介绍 makefile是 ...

  5. C语言:gcc编译过程及make命令、makefile语法规则

    gcc编译过程 编译过程: make && makefile make概述 makefile语法规则 make命令格式 Makefile案例 之所以写成多个文件,是出于模拟多模块编程的 ...

  6. linux环境cpp/c文件的makefile编写(caffe举例)

    编译单个cpp文件 方法一.g++ 文件名.cpp,生成一个名为 "文件名.out" 的可执行文件 方法二.g++ -c 文件名.cpp -o 新文件名.o:生成一个被命名成 &q ...

  7. Linux C编程Makefile编写初步-转

    Linux C编程Makefile编写初步 假设我们有下面这样的一个程序,源代码如下:  /* main.c */  #include "mytool1.h"  #include  ...

  8. Ubuntu下使用gcc和makefile编写c语言程序

    文章目录 前言 一.gcc编写c语言程序 1.hello world的输出 2.简单程序的编译与运行 3.windows环境下的编译运行结果对比 二.makefile编写c语言程序 总结 前言 本文通 ...

  9. linux下MaKefile编写

    Linux下编写 makefile 详细教程 近期在学习Linux下的C编程,买了一本叫<Linux环境下的C编程指南>读到makefile就越看越迷糊,可能是我的理解能不行. 于是goo ...

  10. Linux下的makefile编写 ——陈皓《跟我一起写Makefile》学习笔记(一)

    Linux下的makefile编写 前言 本人记笔记习惯使用OneNote,在学习LinuxC++过程中发现deepin上没有大佬开发或者移植,本人技术也不精,所以决定写博客记笔记(只是习惯问题,并没 ...

最新文章

  1. java中1代表什么_请问java中81是什么意思?
  2. 如果不发论文,我们用什么证明自己的科研实力?
  3. python null byte_如何以“正确”的方式处理带有nullbytes的Python unicode字符串?
  4. 银行计算机记账比赛,在银行柜台业务技术比赛颁奖仪式上的讲话(一).doc
  5. 算法题目——质量(POJ-1862)
  6. 7-7 硬币找钱问题 (10 分)(思路+详解+double类型数据的处理)Come baby!!!!!!!!!!!!!!!!!!!!
  7. php输出1到10的和,php通过排列组合实现1到9数字相加都等于20的方法
  8. python自学入门-初学 Python 者自学 Anaconda 的正确姿势是什么?
  9. 基于Java的Heritrix爬取网页
  10. 融合阿里云,牛客助您找到心仪好工作
  11. mysql无法连接locahost_完美解决MySQL通过localhost无法连接数据库的问题
  12. 三极管的饱和导通条件
  13. 阈值分割:最大类间方差法
  14. MySQL数据分析实战-朱元禄-专题视频课程
  15. HDU 2017 字符串统计(水~)
  16. android光标Cursor
  17. 对于手势的一些思考(转载)
  18. 福建师范大学2022年2月课程考试《形势与政策》作业考核试题
  19. CodeForces 115C. Plumber 解题报告
  20. 蓝桥杯javaB组穿越雷区

热门文章

  1. Java面向对象编程及其三大特征
  2. 使用 jom 代替 nmake
  3. (休息几天)读曼昆之微观经济学——税收归宿
  4. jQuery 常用API
  5. 扫雷win10_手把手教你玩扫雷
  6. Amos24程序安装及注意事项
  7. 3DMax渲染常见问题
  8. 118_网络编程_对IP、网络ID、主机ID、子网掩码、点分十进制的理解
  9. 计算机制图师岗位技能要求,机械制图员
  10. plsql oracle 使用教程