抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

什么是Makefile

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

Makefile文件命名和规则

  • 文件命名

    makefile 或者 Makefile

  • Makefile 规则

    • 一个Makefile文件中可以有一个或者多个规则

      目标 …:依赖 … (… 表示多个依赖)

      ​ (Tab)命令(Shell 命令)

      ​ …

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

make安装

sudo apt install make

make 使用 - 第一版 Makefile

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

sub.c

1
2
3
4
5
6
7
#include <stdio.h>
#include "head.h"

int subtract(int a, int b)
{
return a-b;
}

mult.c

1
2
3
4
5
6
7
#include <stdio.h>
#include "head.h"

int multiply(int a, int b)
{
return a*b;
}

div.c

1
2
3
4
5
6
7
#include <stdio.h>
#include "head.h"

double divide(int a, int b)
{
return (double)a/b;
}

main.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
#include "head.h"

int main()
{
int a = 20;
int b = 12;
printf("a = %d, b = %d\n", a, b);
printf("a + b = %d\n", add(a, b));
printf("a - b = %d\n", subtract(a, b));
printf("a * b = %d\n", multiply(a, b));
printf("a / b = %f\n", divide(a, b));
return 0;
}

head.h

1
2
3
4
5
6
7
8
9
10
11
#ifndef _HEAD_H
#define _HEAD_H
// 加法
int add(int a, int b);
// 减法
int subtract(int a, int b);
// 乘法
int multiply(int a, int b);
// 除法
double divide(int a, int b);
#endif

工作原理

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

第二版 Makefile

1
2
3
4
5
6
7
8
9
10
11
12
app:sub.o add.o mult.o div.o main.o
gcc sub.o mult.o div.o main.o -o app
usb.o:sub.c
gcc -c sub.c -o sub.o
add.o:add.c
gcc -c add.c -o add.o
mult.o:mult.c
gcc -c mult.c -o mult.o
div.o:div.c
gcc -c div.c -o div.o
main.o:main.c
gcc -c main.c -o main.o

变量

  • 自定义变量

    变量名 = 变量值 var = hello $(var)

  • 预定义变量

    AR : 归档维护程序的名称,默认值 ar

    CC : C 编译器的名称,默认值为 cc

    CXX : C++ 编译器的名称。默认值为 g++

    $@ : 目标的完整名称

    $< : 第一个依赖文件名称

    $^ : 所有依赖文件

  • 获取变量的值

    $(变量名)

1
2
3
4
app:main.c a.c b.c 
gcc -c main.c a.c b.c
#自动变量只能在规则的命令中使用 目标就是(app)
$(cc) -c $^ -o $@

第三版 Makefile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 定义变量
src = sub.o add.o mult.o div.o main.o
target = app

$(target):$(src)
$(CC) $(src) -o $(target)

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

模式匹配

1
2
3
4
5
6
7
8
# %.o:%.c
# - %:通配符,匹配一个字符
# - 两个%匹配的是同一个字符串
# %.o:%.c
# gcc -c %< -o $@

sub.o:sub.c
gcc -c sub.c -o sub.o

%<啥意思请点我

第四版 Makefile

1
2
3
4
5
6
7
8
# 定义变量
src = sub.o add.o mult.o div.o main.o
target = app

$(target):$(src)
$(CC) $(src) -o $(target)
%.o:%.c
$(CC) -c $< -o $@

函数

  • $(wildcard PATTERN…)

    • 功能:获取指定目录下指定类型的文件列表

    • 参数:PATTERN指的是某个或多个目录下的对应的某种类型的文件,如果有多个目录,一般使用空格间隔

    • 返回:得到的若干个文件的文件列表,文件之间使用空格间隔

    • 示例

      $(wildcard *.c ./sub/*.c)(第一个*.获取当前目录下的所有.c文件 第二个是./sub 下的所有文件 多个目录可以用空格隔开)

      返回值格式:a.c b.c c.c d.c f.c

  • $(patsubst <pattern>, <replacement>, <text>)

  • 功能:查找<text>中的单词(单词以”空格”、”Tab”或”回车””换行”分割)是否符合模式<pattern>,如果匹配的话,则可以<replacemnt>替换。

    • <sattern>可以包括通配符$,表示任意长度的字串。如果<replacement>中包含$,那么,<replacemnt>中的这个$将是<pattern>中的那个$所代表的字串。(可以用’\‘来转义,以’\%’来表示真实含义的’%’字符)

    • 返回:函数返回被替换过的字符串

    • 示例:

      $(patsubst %.c, %.o, x.c bar.c)

      返回值格式:x.o bar.o

第五版 Makefile

1
2
3
4
5
6
7
8
9
10
# 定义变量
src = $(wildcard ./*.c)
objs = $(patsubst %.c, %.o, $(src))
target = app

$(target):$(objs)
$(CC) $(objs) -o $(target)

%.o:%.c
$(CC) -c $< -o $@

第五版 Makefile

1
2
3
4
5
6
7
8
9
10
# 定义变量
src = $(wildcard ./*.c)
objs = $(patsubst %.c, %.o, $(src))
target = app

$(target):$(objs)
$(CC) $(objs) -o $(target)

%.o:%.c
$(CC) -c $< -o $@

第六版 Makefile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 定义变量
# 可以单独直行一段 make clean
src = $(wildcard ./*.c)
objs = $(patsubst %.c, %.o, $(src))
target = app

$(target):$(objs)
$(CC) $(objs) -o $(target)

%.o:%.c
$(CC) -c $< -o $@

# 因为clean没有依赖可以设置一个尾目标
.PHONY:clean
clean:
rm $(objs) -f

评论