人们通常利用 make 工具来自动完成编译工作。这些工作包括:如果仅修改了某几个源文件,则只重新编译这几个源文件;如果某个头文件被修改了,则重新编译所有包含该头文件的源文件。利用这种自动编译可大大简化开发工作,避免不必要的重新编译。


Makefile

make 工具通过一个称为 makefile 的文件来完成并自动维护编译工作。makefile 需要按照某种语法进行编写,其中说明了如何编译各个源文件并连接生成可执行文件,并定义了源文件之间的依赖关系。当修改了其中某个源文件时,如果其他源文件依赖于该文件,则也要重新编译所有依赖该文件的源文件。

Makefile基本规则

target...:prerequisites...command...

目标(target):程序产生的文件,如可执行文件和目标文件;目标也可以是要执行的动作,如“clean”。

依赖(prerequisites):是用来产生目标的输入文件,一个目标通常依赖于多个文件。

命令(command):是make执行的动作,一个可以有多个命令,每个占一行。注意:每个命令行的起始字符必须为TAB字符!

如果prerequisites中有一个或多个文件更新的话,command就要执行,这就是Makefile最核心的内容

最简单的Makefile例子

源文件有
main.c

#include <stdio.h>
int main(){int a1 = 10, a2 = 20;Swap(a1, a2);printf("swap value : %d ,%d",a1,a2);return 0;
}

swap.h

#ifndef _SWAP_H_
#define _SWAP_H_void Swap(int *a,int *b);#endif

swap.c

#include "swap.h"void Swap(int *a,int *b){int *temp = a;a = b;b = temp;}

将源文件放到同一位置后,用vi Makefile (这里M可以不用大写)命令创建Makefile文件并添加内容如下:

main:main.o swap.ogcc main.o swap.o -o main  //注意空一个tab
main.o:main.c swap.hgcc -c  main.c -o main.o
swap.o:swap.c swap.hgcc -c swap.c -o swap.o
clean:rm -f main main.o swap.o

添加完并保存后,用 make 编译执行而后生成一个 main 文件,用./main执行。


make是如何工作的

1、make会在当前目录下找名字叫“Makefile”或“makefile”。

2、如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“main”这个文件,并把这个文件作为最终的目标文件。

3、如果main文件不存在,或是main所依赖的后面的 .o 文件的文件修改时间要比main这个文件新,那么,他就会执行后面所定义的命令来生成main这个文件。

4、如果main所依赖的.o文件也存在,那么make会在当前文件中找目标为.o文件的依赖性,如果找到则再根据那一个规则生成.o文件。

5、当然,你的C文件和H文件是存在的啦,于是make会生成 .o 文件,然后再用 .o 文件make的终极任务,也就是执行文件main了。


常见伪目标.PHONY

all: target1 target2
Target1:执行make all
install执行make install
Clean执行make clean

Makefile使用伪目标:

main:main.o swap.o gcc main.o swap.o -o main
main.o:main.c swap.hgcc -c main.c -o main.o
swap.o:swap.c swap.hgcc -c swap.c -o swap.o
.PHONY:clean
clean:rm -f main main.o swap.o

(注意:同样是写到Makefile文件里,然后执行make,最后执行生成的可执行文件,下文操作方法都一样。)


Makefile自动化变量

选项名 作用
$@ 规则的目标文件名
$< 规则的第一个依赖文件名
$^ 规则的所有依赖文件列表

makefile中使用变量

objects=main.o swap.o
main:$(objects)gcc $(objects) -o main
main.o:main.c swap.hgcc -c main.c -o main.o
swap.o:swap.c swap.hgcc -c swap.c -o swap.o
.PHONT:clean
clean:rm -f main main.o swap.o

make自动推导

GNU的make很强大,它可以自动推导文件以及文件依赖关系后面的命令,于是我们就没必要去在每一个[.o]文件后都写上类似的命令,因为,我们的make会自动识别,并自己推导命令。

只要make看到一个[.o]文件,它就会自动的把[.c]文件加在依赖关系中,如果make找到一个whatever.o,那么 whatever.c,就会是whatever.o的依赖文件。并且 gcc -c whatever.c 也会被推导出来。

缺点:一旦新增加源文件就要修改

示例

objects= main.o swap.o
main:$(objects)gcc $(objects) -o main
$(objects):
.PHONY:clean
clean:rm -f main *.o

Makefile中常见函数

1、wildcard函数:当前目录下匹配模式的文件
例如:

src=$(wildcard *.c)

2、notdir函数:去除路径
例如:

$(notdir $(src))

3、patsubst函数:模式匹配替换
例如:

$(patsubst%.c,%.o,$(src))等价于 $(src:.c=.o)

4、shell函数:执行shell命令
例如:

 $(shell ls –d */)

优点:不需要修改makefile就能适应

示例

ELF=main
CC=gcc
src=$(wildcard *.c)
objects=$(src:.c=.o)
$(ELF):$(objects)$(CC) $^ -o $@
$(objects):
clean:rm -f $(objects) $(ELF)

多级目录Makefile

ELF=main
CC=gcc
src=$(find -name '*.c')
objects=$(src:.c=.o)
$(ELF):$(objects)
.c.o:$(CC) –c $< -o $@
#$(objects):
clean:rm -f $(objects) $(ELF)

在顶层目录中编写一个Makefile

CC=gcc
SUBDIR=$(shell ls -d */)
ELF = main
ROOTSRC=$(wildcard *.c)
ROOTOBJ=$(ROOTSRC:%.c=%.o)
SUBSRC=$(shell find $(SUBDIR) -name '*.c')
SUBOBJ=$(SUBSRC:%.c=%.o)$(ELF):$(ROOTOBJ) $(SUBOBJ)$(CC) -o $(ELF) $(ROOTOBJ) $(SUBOBJ)
.c.o:echo $(@D) $(<F)  $(@F)$(CC) -c $(@D)/$(<F) -o $(@D)/$(@F)
clean:rm $(ELF) $(ROOTOBJ) $(SUBOBJ)

复习(二)—— Makefile工具使用相关推荐

  1. 【CMake】CMake 引入 ( Android Studio 创建 Native C++ 工程 | C/C++ 源码编译过程 | Makefile 工具 | CMake 引入 )

    文章目录 一.在 Android Studio 中创建 Native C++ 工程 二.C/C++ 源码编译过程 三.Makefile 工具 四.CMake 引入 该系列博客的应用场景是 Androi ...

  2. Linux(二) 常用工具

    Linux(二) 常用工具 一.编辑器 linux常见编辑器有:vi编辑器.vim编辑器.gedit编辑器,还可以用vscode作为编辑器 vi编辑器是Linux内置的编辑器 界面如图所示: vim编 ...

  3. 英语复习二:每单元的翻译篇章

    英语复习二:每单元的翻译篇章 Unit 1 C-E translation 1.中庸思想是儒家思想的核心内容. The Doctrine of the Mean is the core of Conf ...

  4. SQL Server 大数据群集 部署(二)工具篇

    SQL Server 大数据群集 部署(二)工具篇 在进行部署大数据群集之前,先要安装一系列的工具,下表列出了常用的大数据群集工具以及如何安装它们: 工具 Required Description 安 ...

  5. 网络互联复习(二) 精简版

    网络互联复习(二) 精简版 常规配置 配置路由器主机名 禁用 DNS 查找 配置执行模式口令 配置当天消息标题 为控制台连接配置口令 为 VTY 连接配置口令 配置命令为: enable config ...

  6. python基础语法复习[二] 函数、类

    python基础语法复习[二] 前言 一.函数 1.基本概念 2.一般实例 3.参数传递 (1)传不可变对象 (2)传可变对象 4.函数递归调用实例 (1)eg:实现字符串的反转: (2)递归思想画树 ...

  7. jeesite实战(二)——jeesite工具生成基本的页面

    系列文章目录 jeesite实战(一)--基本环境搭建 jeesite实战(二)--jeesite工具生成基本的页面 提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 系列文 ...

  8. 2.说明计算机环境下会计循环的八个流程,2020年云南自考《会计信息系统》要点复习(二)...

    对于考生们来说,想要尽早通过云南成人自考拿到自学考试的本科毕业证书,一定要制定合理的复习备考计划.此外,考生们来说大多都是在职备考的状态,考生们大多没有时间进行复习备考工作.为了帮助考生们更好的进行复 ...

  9. 数控技术复习(二):数控编程必备的基础知识

    文章首发于个人博客,欢迎访问:数控技术复习(二):数控编程必备的基础知识 数控机床加工零件:零件图代码->程序单->控制介质->数控装置->伺服电机->机床自动加工.从零 ...

  10. JAVA二开工具开源 (三)--多租户实现方案

    JAVA二开工具开源 (三)–多租户实现方案 最近想了解如何Java对接微信平台,快速搭建完整项目开发,发现网上有很对开源的这类二开源码.https://gitee.com/luozijing123/ ...

最新文章

  1. 《云计算:概念、技术与架构》一2.3 案例研究3:Innovartus
  2. str_repeat() 函数
  3. 当前不会命中断点.还没有为该文档加载任何符号解决
  4. python中math isnan,在python中指定一个变量NaN,不用numpy
  5. undefined symbol: sqlite3_open_v2
  6. Oracle 检查点队列和HASH Bucket
  7. 宝塔面板服务器ip地址修改_「网站」快速搭建服务器环境及网站
  8. csv导入mysql_mysql导入超大csv指南
  9. 如何面试一位前端工程师
  10. Iphone隐藏和显示TabBar的方法
  11. 使用技巧-输出彩色TIF格式分类结果
  12. 无法启动程序因为计算机中丢失msvcr100,devenv.exe 系统错误无法启动此程序,因为计算机中丢失 MSVCR100.dll问题的解决办法...
  13. 用Unity的GetSpectrumData方法识别钢琴曲中的钢琴琴键
  14. 红黑树-Java实现
  15. 灵敏度分享码显示服务器不可用,和平精英S11最稳灵敏度分享码有哪些?和平精英灵敏度设置分享码...
  16. 在Linux(BackTrack5)下安装卡无线网
  17. 【每日新闻】苹果公布新实验室:机器人每年回收120万部iPhone
  18. 移动端组件库ThorUI正确引入小程序方式
  19. 三星gtn8010安卓7_三星平板N8000刷机升级安卓版本到7.1过程记录
  20. 汉字字符内码查询_VB小程序,字符与内码

热门文章

  1. python 面向对象 (一)
  2. vue init webpack缺少标识符_vue 如何从单页应用改造成多页应用_vue.js
  3. 李宏毅线性代数笔记2: 线性方程组和数域
  4. 产品经理经验谈50篇(四):数据分析常用方法及应用案例解析
  5. 数据挖掘学习笔记--决策树C4.5
  6. python实现自动发送微博,当自己写博客时同步上去。
  7. python 统计list中各个元素出现的次数
  8. Python中numpy库unique函数解析
  9. 使用JSON Web Token设计单点登录系统--转
  10. 并发编程 — 并发数据结构--转载