Makefile的那些事

阶段三就要完成了下面的课程将是我更所期待的

makefile在工程很多时可以用自动编译将效率提高很多

在用makefile之前需要安装make,本人是ubuntu系统所以直接

sudo apt-get install make

Makefile的本质是一个文件需要配合make命令进行自动化编译文件名常首字母大写
在Makefile中的格式为:
<目标> : <依赖>
一个TAB<命令>
Makefile的 = 赋值的话有个易错点就是变量按照最后一次赋的值而进行具体的意思就是

1
2
3
4
5
6
7
OBJ1 = A
OBJ2 = $(OBJ1A) B
OBJ1 = AA
all :
@echo ${OBJ2}
//经过上面的赋值后OBJ2的值为 AA B


:= 表示直接赋值赋予当前位置的值
像上面的例子最终结果就是A B


自动变量

$@ 在我个人定义中这个就是匹配当前的目标

$< 依赖文件集合中的第一个文件.

$^ 所有依赖文件的集合使用空格分开如果在依赖文件中有多个重复的文件会去除重复的依赖文件只保留一份


例如说

我创建了一个fun.h,fun.c以及main.c我一般编译的话直接gcc *.c就行了从而创建出可执行的a.out我如果要用makefile的话:

1
2
3
4
5
6
7
8
9
10
11
cc := gcc
TARGET := main_exec#目标
OBJECT := main.o fun.o#可执行文件依赖
${TARGET} : ${OBJECT}
@${cc} $^ -o $@
%.o : %.c
@$(CC) -c $< -o $@
#特别解释一下%,这里的%是匹配规则和*是不同的上面的%.c代表匹配到的.c文件逐一进行命令*仅仅代表所有的.c文件
#因为我们的依赖文件有两个所以相当于执行了两次
clean :
rm -rf *.o main_exec

疑惑点:
为什么OBJECT可以被赋多个值
答: Makefile中的变量赋值类似与c语言中的宏可以理解为直接替换


Makefile静态模式

Makefile的静态模式指的是一种自动编译模式在这种模式下我们可以很容易的定义"多目标"规则语法如下:

1
2
3
4
5
<targets ...> : <target-pattern> : <prereq-patterns...>
<command>
// target 定义了一系列目标也就是多个目标可以是通配符也可以是多个目标的集合
//target-pattern 是targets的模式也就是目标集模式浅显点在上文可以理解为%.o
//prereq-patterns 则是目标的依赖元素

示例:

1
2
3
$(OBJS) : %.o : %.c
gcc -c $< -o $@
//$(OBJS是多个.o文件的集合例如: fun.o glob.o main.o

伪目标.PHONY:

当makefile目录下有一个和目标相同的文件时例如clean文件我们在执行make命令的时候会出现错误伪目标就是用于解决此种错误而产生伪目标只是一个标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
.PHONY  clean
CC := gcc

TARGET : exec_main
OBJECT : main.o fun.o

$(TARGET) : $(OBJECT)
$(CC) -O $@ $^

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

clean:
rm -rf *.o exec_main

指定头文件:

linux中一般通过"-I" 大写i)来指定头文件,形式如下

1
-I  /home/linux/include

Makefile中常见写法:

1
2
3
4
5
 CFLAGS = -I /home/linux/include

myapp: *.c
gcc $(CFLAGS) -o myapp

指定库文件路径:

linux中一般通过"-L" 大写l)来指定库文件的路径,形式如下:

1
LDFLAGS = -L /usr/lib