首页 > 其他分享 >(三)Makefile

(三)Makefile

时间:2022-10-22 13:56:03浏览次数:65  
标签:sub Makefile add div main mult

1 什么是Makefile

  • 一个工程中的源文件不计其数,其按类型、功能、模块分别放在若干个目录中,Makefile 文件定义了一系列的规则来指定哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为 Makefile 文件就像一个 Shell 脚本一样,也可以执行操作系统的命令。
  • Makefile 带来的好处就是“自动化编译” ,一旦写好,只需要一个 make 命令,整个工程完全自动编译,极大的提高了软件开发的效率。make 是一个命令工具,是一个解释 Makefile 文件中指令的命令工具,一般来说,大多数的 IDE 都有这个命令,比如 Delphi 的 make,Visual C++ 的 nmake,Linux 下 GNU 的 make。

2 Makefile文件命名和规则

  • 文件命名
    makefile或者Makefile
  • Makefile 规则
    • 一个 Makefile 文件中可以有一个或者多个规则。
    目标 ...: 依赖 ...
    	命令(Shell 命令)
    	...
    

    目标:最终要生成的文件(伪目标除外)
    依赖:生成目标所需要的文件或是目标
    命令:通过执行命令对依赖操作生成目标(命令前必须 Tab 缩进)

    • Makefile 中的其它规则一般都是为第一条规则服务的。

    若后面的某一条规则与第一条规则没有任何关系,则不会执行

当前目录如下:

.
├── add.c
├── div.c
├── head.h
├── main.c
├── Makefile
├── mult.c
└── sub.c

Makefile

app:add.c div.c mult.c sub.c main.c
	gcc add.c div.c mult.c sub.c main.c -o app

执行make命令,生成可执行文件

root@LDY:~/cpp-study/lesson07/calc# make
gcc add.c div.c mult.c sub.c main.c -o app

3 工作原理

  • 命令在执行之前,需要先检查规则中的依赖是否存在
    • 如果存在,执行命令
    • 如果不存在,向下检查其它的规则,检查有没有一个规则是用来生成这个依赖的,如果找到了,则执行该规则中的命令
  • 检测更新,在执行规则中的命令时,会比较目标和依赖文件的时间
    • 如果依赖的时间比目标的时间晚,需要重新生成目标
    • 如果依赖的时间比目标的时间早,目标不需要更新,对应规则中的命令不需要被执行

改写 2 中的 Makefile 文件,每个源文件都生成.o文件。好处是如果只更新了部分文件,不会全部编译,只会编译与更新文件有关的部分。

app:add.o div.o mult.o sub.o main.o
	gcc add.o div.o mult.o sub.o main.o -o app
add.o:add.c
	gcc -c add.c -o add.o
div.o:div.c
	gcc -c div.c -o div.o
mult.o:mult.c
	gcc -c mult.c -o mult.o
sub.o:sub.c
	gcc -c sub.c -o sub.o
main.o:main.c
	gcc -c main.c -o main.o

执行 make 命令。

root@LDY:~/cpp-study/lesson07/calc# make
gcc -c add.c -o add.o
gcc -c div.c -o div.o
gcc -c mult.c -o mult.o
gcc -c sub.c -o sub.o
gcc -c main.c -o main.o
gcc add.o div.o mult.o sub.o main.o -o app
.
├── add.c
├── add.o
├── app
├── div.c
├── div.o
├── head.h
├── main.c
├── main.o
├── Makefile
├── mult.c
├── mult.o
├── sub.c
└── sub.o

再次执行,因为没有依赖更新,所以没有执行。

root@LDY:~/cpp-study/lesson07/calc# make
make: 'app' is up to date.

修改 main.c 后再执行,只更新了部分。

root@LDY:~/cpp-study/lesson07/calc# make
gcc -c main.c -o main.o
gcc add.o div.o mult.o sub.o main.o -o app

4 变量

  • 自定义变量
    变量名=变量值

    例如:var=hello

  • 获取变量的值
    $(变量名)

    例如 $(var)

  • 预定义变量
    AR : 归档维护程序的名称,默认值为 ar
    CC : C 编译器的名称,默认值为 cc
    CXX : C++ 编译器的名称,默认值为 g++
    $@ : 目标的完整名称
    $< : 第一个依赖文件的名称
    $^ : 所有的依赖文件

    其中$@ $< $^被称为自动变量,自动变量只能在规则的命令中使用。例如:

    app:main.c a.c b.c
        gcc -c main.c a.c b.c
    # 可以用自动变量写成
    app:main.c a.c b.c
        $(CC) -c $^ -o $@
    

5 模式匹配

  • %.o:%.c
    • %: 通配符,匹配一个字符串
    • 两个%匹配的是同一个字符串

通过定义变量和模式匹配,可以将 3 中的 Makefile 改写为以下形式。

# 定义变量
objs = add.o div.o mult.o sub.o main.o
target = app
$(target):$(objs)
	$(CC) $(objs) -o $(target)

# 模式匹配
%.o:%.c
	$(CC) -c $< -o $@

6 函数

  • $(wildcard PATTERN...)
    • 功能:获取指定目录下指定类型的文件列表
    • 参数:PATTERN指的是某个或多个目录下的对应的某种类型的文件,如果有多个目录,一般使用空格间隔
    • 返回:得到的若干个文件的文件列表,文件名之间使用空格间隔
    • 示例:
    $(wildcard *.c ./sub/*.c)
    返回值格式: a.c b.c c.c d.c e.c f.c
    
  • $(patsubst <pattern>,<replacement>,<text>)
    • 功能:查找<text>中的单词(单词以“空格”、“Tab”、“回车”、或“换行”分隔)是否符合模式<pattern>,如果匹配的话,则以<replacement>替换。
    • <pattern>可以包括通配符%,表示任意长度的字串。如果<replacement>中也包含%,那么,<replacement>中的这个%将是<pattern>中的那个%所代表的字串。(可以用\来转义,以\%来表示真实含义的%字符)。
    • 返回:函数返回被替换过后的字符串。
    • 示例:
    $(patsubst %.c, %.o, x.c bar.c)
    返回值格式: x.o bar.o
    

用函数改写 5 中的 Makefile,同时添加清除的伪指令,清除中间生成的 .o 文件。

# 定义变量
target = app
# 调用函数
# 查找源文件.c
src = $(wildcard ./*.c)
# 替换成.o文件
objs = $(patsubst %.c, %.o, $(src))
$(target):$(objs)
	$(CC) $(objs) -o $(target)

# 模式匹配
%.o:%.c
	$(CC) -c $< -o $@

# 删除.o文件
# 伪目标,不会生成目标文件
.PHONY:clean
clean:
	rm $(objs) -f

clean不会被执行,需要显式执行 make clean,清除后的目录如下。

.
├── add.c
├── app
├── div.c
├── head.h
├── main.c
├── Makefile
├── mult.c
└── sub.c

不加为目标指令.PHONY:clean,如果文件夹中有clean文件,则无法执行make clean

标签:sub,Makefile,add,div,main,mult
From: https://www.cnblogs.com/dalelee/p/16814622.html

相关文章

  • Makefile
    MAKEFILE学习视频地址:https://www.bilibili.com/video/BV1Xt4y1h7rH/?p=2&vd_source=305f791c703672cea3129189ddda734f目标:一般指要编译的目标,也可以是一个动作依赖:指执行......
  • makefile学习
    makefile书写规则TARGET...:PREREQUISITES...COMMANDTARGET:规则目标,可以是一个objectfile(目标文件),也可以是一个执行文件,还可以是一个标签(label)。PREREQUISITE......
  • Linux系统编程04-Makefile
    文件命名:makefile或Makefile规则:一个Makefile文件中可以有一个或多个规则目标...:依赖...​ 命令(shell命令)​ ...目标:最终生成的文件依赖:......
  • 【AI白身境】只会用Python?g++,CMake和Makefile了解一下
    今天是新专栏《AI白身境》的第六篇,所谓白身,就是什么都不会,还没有进入角色。对于大部分小白来说,因为python用的太爽,以致于或许都没有听说过CMake。python是脚本语言,而当前大......
  • 第2天 汇编语言与makeFile
    汇编orgorigin表示程序加载的开始地址,也就是将程序从什么位置进行加载JMP相当于c语言的goto语句,无条件跳转。jmpentry表示跳转到entry语句块。MOV数据传送指令,需......
  • VScode开发STM32/GD32单片机-MakeFile工程JlinkRTT配置
    本次使用开发板为STM32F401CCU6,使用CubeMX配置一个Makefile工程  配置时候为内部时钟  工程选择makefile工程类型 只生成需要的文件  用VSCode打开后显......
  • Can't exec "mysql_config": No such file or directory at Makefile.PL line 89.
     001、问题Can'texec"mysql_config":NosuchfileordirectoryatMakefile.PLline89.  002、解决方法(base)[[email protected]]#yuminstal......
  • make/Makefile --- 默认规则
    make有一条默认规则,当找不到xxx.o文件时,会查找目录下的同名xxx.c文件进行编译MakeFile:  make ......
  • GDB及Makefile学习
    GDB(1)下载安装gdb:sudoapt-getinstallgdb(2)启动gdbgdbtest(3)启动后界面如下:参考老师所给ppt内容我们可以输入(gdb)l列出文件的代码清单·(gdb)b1.函数......
  • makefile2
    一、make执行解析与实例操作1、#make后没有指定,只执行第一个定义。优先执行依赖,依赖没有就依次查找依赖,找到后执行依赖生成文件,在继续执行。make-s#不打印输出命令例1......